@@ -9,11 +9,12 @@ pub enum CommandCodecError {
99}
1010
1111#[ must_use]
12- pub fn encode_client_request ( request : ClientRequest ) -> Vec < u8 > {
12+ pub fn encode_client_request ( request : impl AsRef < ClientRequest > ) -> Vec < u8 > {
13+ let request = request. as_ref ( ) ;
1314 let mut bytes = Vec :: new ( ) ;
1415 bytes. extend_from_slice ( & request. operation_id . get ( ) . to_le_bytes ( ) ) ;
1516 bytes. extend_from_slice ( & request. client_id . get ( ) . to_le_bytes ( ) ) ;
16- encode_command ( & mut bytes, request. command ) ;
17+ encode_command ( & mut bytes, & request. command ) ;
1718 bytes
1819}
1920
@@ -36,7 +37,8 @@ pub fn decode_client_request(bytes: &[u8]) -> Result<ClientRequest, CommandCodec
3637}
3738
3839#[ must_use]
39- pub fn encode_internal_command ( command : Command ) -> Vec < u8 > {
40+ pub fn encode_internal_command ( command : impl AsRef < Command > ) -> Vec < u8 > {
41+ let command = command. as_ref ( ) ;
4042 let mut bytes = Vec :: new ( ) ;
4143 encode_command ( & mut bytes, command) ;
4244 bytes
@@ -54,7 +56,7 @@ pub fn decode_internal_command(bytes: &[u8]) -> Result<Command, CommandCodecErro
5456 Ok ( command)
5557}
5658
57- fn encode_command ( bytes : & mut Vec < u8 > , command : Command ) {
59+ fn encode_command ( bytes : & mut Vec < u8 > , command : & Command ) {
5860 match command {
5961 Command :: CreateResource { resource_id } => {
6062 bytes. push ( 1 ) ;
@@ -70,27 +72,44 @@ fn encode_command(bytes: &mut Vec<u8>, command: Command) {
7072 bytes. extend_from_slice ( & holder_id. get ( ) . to_le_bytes ( ) ) ;
7173 bytes. extend_from_slice ( & ttl_slots. to_le_bytes ( ) ) ;
7274 }
75+ Command :: ReserveBundle {
76+ resource_ids,
77+ holder_id,
78+ ttl_slots,
79+ } => {
80+ bytes. push ( 3 ) ;
81+ bytes. extend_from_slice (
82+ & u32:: try_from ( resource_ids. len ( ) )
83+ . expect ( "bundle len must fit u32" )
84+ . to_le_bytes ( ) ,
85+ ) ;
86+ for resource_id in resource_ids {
87+ bytes. extend_from_slice ( & resource_id. get ( ) . to_le_bytes ( ) ) ;
88+ }
89+ bytes. extend_from_slice ( & holder_id. get ( ) . to_le_bytes ( ) ) ;
90+ bytes. extend_from_slice ( & ttl_slots. to_le_bytes ( ) ) ;
91+ }
7392 Command :: Confirm {
7493 reservation_id,
7594 holder_id,
7695 } => {
77- bytes. push ( 3 ) ;
96+ bytes. push ( 4 ) ;
7897 bytes. extend_from_slice ( & reservation_id. get ( ) . to_le_bytes ( ) ) ;
7998 bytes. extend_from_slice ( & holder_id. get ( ) . to_le_bytes ( ) ) ;
8099 }
81100 Command :: Release {
82101 reservation_id,
83102 holder_id,
84103 } => {
85- bytes. push ( 4 ) ;
104+ bytes. push ( 5 ) ;
86105 bytes. extend_from_slice ( & reservation_id. get ( ) . to_le_bytes ( ) ) ;
87106 bytes. extend_from_slice ( & holder_id. get ( ) . to_le_bytes ( ) ) ;
88107 }
89108 Command :: Expire {
90109 reservation_id,
91110 deadline_slot,
92111 } => {
93- bytes. push ( 5 ) ;
112+ bytes. push ( 6 ) ;
94113 bytes. extend_from_slice ( & reservation_id. get ( ) . to_le_bytes ( ) ) ;
95114 bytes. extend_from_slice ( & deadline_slot. get ( ) . to_le_bytes ( ) ) ;
96115 }
@@ -107,15 +126,28 @@ fn decode_command(cursor: &mut Cursor<'_>) -> Result<Command, CommandCodecError>
107126 holder_id : HolderId ( cursor. read_u128 ( ) ?) ,
108127 ttl_slots : cursor. read_u64 ( ) ?,
109128 } ) ,
110- 3 => Ok ( Command :: Confirm {
129+ 3 => {
130+ let resource_count = usize:: try_from ( cursor. read_u32 ( ) ?)
131+ . map_err ( |_| CommandCodecError :: InvalidLayout ) ?;
132+ let mut resource_ids = Vec :: with_capacity ( resource_count) ;
133+ for _ in 0 ..resource_count {
134+ resource_ids. push ( ResourceId ( cursor. read_u128 ( ) ?) ) ;
135+ }
136+ Ok ( Command :: ReserveBundle {
137+ resource_ids,
138+ holder_id : HolderId ( cursor. read_u128 ( ) ?) ,
139+ ttl_slots : cursor. read_u64 ( ) ?,
140+ } )
141+ }
142+ 4 => Ok ( Command :: Confirm {
111143 reservation_id : ReservationId ( cursor. read_u128 ( ) ?) ,
112144 holder_id : HolderId ( cursor. read_u128 ( ) ?) ,
113145 } ) ,
114- 4 => Ok ( Command :: Release {
146+ 5 => Ok ( Command :: Release {
115147 reservation_id : ReservationId ( cursor. read_u128 ( ) ?) ,
116148 holder_id : HolderId ( cursor. read_u128 ( ) ?) ,
117149 } ) ,
118- 5 => Ok ( Command :: Expire {
150+ 6 => Ok ( Command :: Expire {
119151 reservation_id : ReservationId ( cursor. read_u128 ( ) ?) ,
120152 deadline_slot : Slot ( cursor. read_u64 ( ) ?) ,
121153 } ) ,
@@ -160,6 +192,10 @@ impl<'a> Cursor<'a> {
160192 Ok ( u64:: from_le_bytes ( self . read_exact :: < 8 > ( ) ?) )
161193 }
162194
195+ fn read_u32 ( & mut self ) -> Result < u32 , CommandCodecError > {
196+ Ok ( u32:: from_le_bytes ( self . read_exact :: < 4 > ( ) ?) )
197+ }
198+
163199 fn read_u128 ( & mut self ) -> Result < u128 , CommandCodecError > {
164200 Ok ( u128:: from_le_bytes ( self . read_exact :: < 16 > ( ) ?) )
165201 }
@@ -187,7 +223,7 @@ mod tests {
187223 } ,
188224 } ;
189225
190- let decoded = decode_client_request ( & encode_client_request ( request) ) . unwrap ( ) ;
226+ let decoded = decode_client_request ( & encode_client_request ( & request) ) . unwrap ( ) ;
191227 assert_eq ! ( decoded, request) ;
192228 }
193229
@@ -198,10 +234,26 @@ mod tests {
198234 deadline_slot : Slot ( 42 ) ,
199235 } ;
200236
201- let decoded = decode_internal_command ( & encode_internal_command ( command) ) . unwrap ( ) ;
237+ let decoded = decode_internal_command ( & encode_internal_command ( & command) ) . unwrap ( ) ;
202238 assert_eq ! ( decoded, command) ;
203239 }
204240
241+ #[ test]
242+ fn reserve_bundle_round_trips ( ) {
243+ let request = ClientRequest {
244+ operation_id : OperationId ( 11 ) ,
245+ client_id : ClientId ( 12 ) ,
246+ command : Command :: ReserveBundle {
247+ resource_ids : vec ! [ ResourceId ( 13 ) , ResourceId ( 14 ) ] ,
248+ holder_id : HolderId ( 15 ) ,
249+ ttl_slots : 16 ,
250+ } ,
251+ } ;
252+
253+ let decoded = decode_client_request ( & encode_client_request ( & request) ) . unwrap ( ) ;
254+ assert_eq ! ( decoded, request) ;
255+ }
256+
205257 #[ test]
206258 fn decoder_rejects_truncated_payload ( ) {
207259 let request = ClientRequest {
@@ -211,7 +263,7 @@ mod tests {
211263 resource_id : ResourceId ( 3 ) ,
212264 } ,
213265 } ;
214- let mut bytes = encode_client_request ( request) ;
266+ let mut bytes = encode_client_request ( & request) ;
215267 bytes. pop ( ) ;
216268
217269 assert_eq ! (
0 commit comments