@@ -20,28 +20,28 @@ fn empty(address: Pubkey) -> Account {
2020 }
2121}
2222
23- /// Build create_address_info instruction data manually.
23+ /// Build the create_address_info instruction data using Quasar's compact
24+ /// wire format: a header containing all fixed fields and length prefixes,
25+ /// followed by a tail with all dynamic byte payloads grouped together.
2426///
25- /// Wire format (from reading the #[instruction] codegen):
26- /// [disc: 1 byte]
27- /// [ZC struct: house_number u8]
28- /// [name: u32 LE length prefix + bytes] (String → DynKind::Str with U32 prefix)
29- /// [street: u32 LE length prefix + bytes]
30- /// [city: u32 LE length prefix + bytes]
27+ /// Layout:
28+ /// header: [disc: u8 = 0][house_number: u8][name_len: u8][street_len: u8][city_len: u8]
29+ /// tail: [name bytes][street bytes][city bytes]
30+ ///
31+ /// `String<50>` defaults to a u8 length prefix because MAX (50) fits in a byte.
3132fn build_create_instruction_data ( name : & str , house_number : u8 , street : & str , city : & str ) -> Vec < u8 > {
32- let mut data = vec ! [ 0u8 ] ; // discriminator = 0
33+ let mut data = Vec :: with_capacity ( 5 + name . len ( ) + street . len ( ) + city . len ( ) ) ;
3334
34- // Fixed ZC struct: house_number
35+ // Header
36+ data. push ( 0u8 ) ; // instruction discriminator
3537 data. push ( house_number) ;
38+ data. push ( name. len ( ) as u8 ) ;
39+ data. push ( street. len ( ) as u8 ) ;
40+ data. push ( city. len ( ) as u8 ) ;
3641
37- // Dynamic String args with u32 length prefix
38- data. extend_from_slice ( & ( name. len ( ) as u32 ) . to_le_bytes ( ) ) ;
42+ // Tail
3943 data. extend_from_slice ( name. as_bytes ( ) ) ;
40-
41- data. extend_from_slice ( & ( street. len ( ) as u32 ) . to_le_bytes ( ) ) ;
4244 data. extend_from_slice ( street. as_bytes ( ) ) ;
43-
44- data. extend_from_slice ( & ( city. len ( ) as u32 ) . to_le_bytes ( ) ) ;
4545 data. extend_from_slice ( city. as_bytes ( ) ) ;
4646
4747 data
@@ -81,34 +81,25 @@ fn test_create_address_info() {
8181 // Verify the account data.
8282 let account = result. account ( & address_info) . unwrap ( ) ;
8383
84- // Onchain layout (from #[account] dynamic codegen):
85- // [disc: 1 byte = 1]
86- // [ZC header: house_number u8]
87- // [name: u8 prefix + bytes] (String<u8, 50> uses u8 prefix)
88- // [street: u8 prefix + bytes]
89- // [city: u8 prefix + bytes]
84+ // Onchain layout for a Quasar ` #[account]` with dynamic fields uses the
85+ // compact "header then tail" format. Length prefixes are grouped in the
86+ // header, the actual bytes follow in the tail.
87+ // header: [disc: 1][house_number: u8][name_len: u8][street_len: u8][city_len: u8]
88+ // tail: [name bytes][street bytes][city bytes]
89+ // String<50> defaults to a u8 length prefix because MAX (50) fits in a byte.
9090 assert_eq ! ( account. data[ 0 ] , 1 , "discriminator" ) ;
9191 assert_eq ! ( account. data[ 1 ] , 42 , "house_number" ) ;
92-
93- let mut offset = 2 ;
94-
95- // name: u8 prefix + "Alice"
96- let name_len = account. data [ offset] as usize ;
97- offset += 1 ;
92+ let name_len = account. data [ 2 ] as usize ;
93+ let street_len = account. data [ 3 ] as usize ;
94+ let city_len = account. data [ 4 ] as usize ;
9895 assert_eq ! ( name_len, 5 ) ;
99- assert_eq ! ( & account. data[ offset..offset + name_len] , b"Alice" ) ;
100- offset += name_len;
101-
102- // street: u8 prefix + "Main Street"
103- let street_len = account. data [ offset] as usize ;
104- offset += 1 ;
10596 assert_eq ! ( street_len, 11 ) ;
106- assert_eq ! ( & account. data[ offset..offset + street_len] , b"Main Street" ) ;
107- offset += street_len;
108-
109- // city: u8 prefix + "New York"
110- let city_len = account. data [ offset] as usize ;
111- offset += 1 ;
11297 assert_eq ! ( city_len, 8 ) ;
113- assert_eq ! ( & account. data[ offset..offset + city_len] , b"New York" ) ;
98+
99+ let header_end = 5 ;
100+ assert_eq ! ( & account. data[ header_end..header_end + name_len] , b"Alice" ) ;
101+ let street_start = header_end + name_len;
102+ assert_eq ! ( & account. data[ street_start..street_start + street_len] , b"Main Street" ) ;
103+ let city_start = street_start + street_len;
104+ assert_eq ! ( & account. data[ city_start..city_start + city_len] , b"New York" ) ;
114105}
0 commit comments