11#![ forbid( unsafe_code, missing_docs) ]
22#![ cfg_attr( test, deny( warnings) ) ]
3-
43//! # Series of compact encoding schemes for building small and fast parsers and serializers
54//!
65//! Binary compatible with the
@@ -164,7 +163,7 @@ mod fixedwidth;
164163pub use fixedwidth:: { FixedWidthEncoding , FixedWidthU32 , FixedWidthU64 , FixedWidthUint } ;
165164use std:: {
166165 any:: type_name,
167- net:: { Ipv4Addr , Ipv6Addr } ,
166+ net:: { Ipv4Addr , Ipv6Addr , SocketAddrV4 , SocketAddrV6 } ,
168167} ;
169168
170169pub use crate :: error:: { EncodingError , EncodingErrorKind } ;
@@ -180,6 +179,17 @@ const U16_SIZE: usize = 2;
180179const U32_SIZE : usize = 4 ;
181180const U64_SIZE : usize = 8 ;
182181
182+ /// Encoded size of a network port
183+ pub const PORT_ENCODED_SIZE : usize = 2 ;
184+ /// Encoded size of an ipv4 address
185+ pub const IPV4_ADDR_ENCODED_SIZE : usize = U32_SIZE ;
186+ /// Encoded size of an ipv6 address
187+ pub const IPV6_ADDR_ENCODED_SIZE : usize = 16 ;
188+ /// Encoded size for a [`SocketAddrV4`], an ipv4 address plus port.
189+ pub const SOCKET_ADDR_V4_ENCODED_SIZE : usize = IPV4_ADDR_ENCODED_SIZE + PORT_ENCODED_SIZE ;
190+ /// Encoded size for a [`SocketAddrV6`], an ipv6 address plus port.
191+ pub const SOCKET_ADDR_V6_ENCODED_SIZE : usize = IPV6_ADDR_ENCODED_SIZE + PORT_ENCODED_SIZE ;
192+
183193/// A trait for building small and fast parsers and serializers.
184194pub trait CompactEncoding < Decode : ?Sized = Self > {
185195 /// The size in bytes required to encode `self`.
@@ -433,8 +443,20 @@ macro_rules! map_decode {
433443 } } ;
434444}
435445
436- /// helper for mapping the first element of a two eleent tuple
446+ #[ macro_export]
447+ /// Helper for mapping the first element of a two eleent tuple.
448+ /// This is useful for cleanly handling the result of CompactEncoding::decode.
437449macro_rules! map_first {
450+ ( $res: expr, $f: expr) => { {
451+ let ( one, two) = $res;
452+ let mapped = $f( one) ;
453+ ( mapped, two)
454+ } } ;
455+ }
456+
457+ #[ macro_export]
458+ /// like [`map_first`] but the mapping should return a result.
459+ macro_rules! map_first_result {
438460 ( $res: expr, $f: expr) => { {
439461 let ( one, two) = $res;
440462 let mapped = $f( one) ?;
@@ -514,7 +536,7 @@ pub fn take_array<const N: usize>(
514536) -> std:: result:: Result < ( [ u8 ; N ] , & [ u8 ] ) , EncodingError > {
515537 let Some ( ( out, rest) ) = buffer. split_first_chunk :: < N > ( ) else {
516538 return Err ( EncodingError :: out_of_bounds ( & format ! (
517- "Could not write [{}] bytes to buffer of length [{}]" ,
539+ "Could not take [{}] bytes from buffer of length [{}]" ,
518540 N ,
519541 buffer. len( )
520542 ) ) ) ;
@@ -607,16 +629,14 @@ pub fn decode_usize(buffer: &[u8]) -> Result<(usize, &[u8]), EncodingError> {
607629 let ( [ first] , rest) = take_array :: < 1 > ( buffer) ?;
608630 Ok ( match first {
609631 x if x < U16_SIGNIFIER => ( x. into ( ) , rest) ,
610- U16_SIGNIFIER => map_first ! ( decode_u16( rest) ?, |x: u16 | Ok ( x. into( ) ) ) ,
632+ U16_SIGNIFIER => map_first ! ( decode_u16( rest) ?, |x: u16 | x. into( ) ) ,
611633 U32_SIGNIFIER => {
612- map_first ! ( decode_u32( rest) ?, |val| usize :: try_from( val) . map_err(
613- |_| EncodingError :: overflow( "Could not convert u32 to usize" )
614- ) )
634+ map_first_result ! ( decode_u32( rest) ?, |val| usize :: try_from( val)
635+ . map_err( |_| EncodingError :: overflow( "Could not convert u32 to usize" ) ) )
615636 }
616637 _ => {
617- map_first ! ( decode_u64( rest) ?, |val| usize :: try_from( val) . map_err(
618- |_| EncodingError :: overflow( "Could not convert u64 to usize" )
619- ) )
638+ map_first_result ! ( decode_u64( rest) ?, |val| usize :: try_from( val)
639+ . map_err( |_| EncodingError :: overflow( "Could not convert u64 to usize" ) ) )
620640 }
621641 } )
622642}
@@ -684,8 +704,8 @@ fn decode_u64_var(buffer: &[u8]) -> Result<(u64, &[u8]), EncodingError> {
684704 let ( [ first] , rest) = take_array :: < 1 > ( buffer) ?;
685705 Ok ( match first {
686706 x if x < U16_SIGNIFIER => ( x. into ( ) , rest) ,
687- U16_SIGNIFIER => map_first ! ( decode_u16( rest) ?, |x: u16 | Ok ( x. into( ) ) ) ,
688- U32_SIGNIFIER => map_first ! ( decode_u32( rest) ?, |x: u32 | Ok ( x. into( ) ) ) ,
707+ U16_SIGNIFIER => map_first ! ( decode_u16( rest) ?, |x: u16 | x. into( ) ) ,
708+ U32_SIGNIFIER => map_first ! ( decode_u32( rest) ?, |x: u32 | x. into( ) ) ,
689709 _ => decode_u64 ( rest) ?,
690710 } )
691711}
@@ -717,7 +737,8 @@ fn encode_u64(val: u64, buffer: &mut [u8]) -> Result<&mut [u8], EncodingError> {
717737 write_array ( & val. to_le_bytes ( ) , buffer)
718738}
719739
720- fn encode_usize_var < ' a > (
740+ /// Encode a `usize` in a variable width way
741+ pub fn encode_usize_var < ' a > (
721742 value : & usize ,
722743 buffer : & ' a mut [ u8 ] ,
723744) -> Result < & ' a mut [ u8 ] , EncodingError > {
@@ -838,6 +859,23 @@ impl CompactEncoding for u64 {
838859 }
839860}
840861
862+ impl CompactEncoding for usize {
863+ fn encoded_size ( & self ) -> Result < usize , EncodingError > {
864+ Ok ( encoded_size_usize ( * self ) )
865+ }
866+
867+ fn encode < ' a > ( & self , buffer : & ' a mut [ u8 ] ) -> Result < & ' a mut [ u8 ] , EncodingError > {
868+ encode_usize_var ( self , buffer)
869+ }
870+
871+ fn decode ( buffer : & [ u8 ] ) -> Result < ( Self , & [ u8 ] ) , EncodingError >
872+ where
873+ Self : Sized ,
874+ {
875+ decode_usize ( buffer)
876+ }
877+ }
878+
841879impl CompactEncoding for String {
842880 fn encoded_size ( & self ) -> Result < usize , EncodingError > {
843881 encoded_size_str ( self )
@@ -947,11 +985,20 @@ impl CompactEncoding for Ipv4Addr {
947985 Ok ( ( Ipv4Addr :: from ( * dest) , rest) )
948986 }
949987}
988+
950989impl CompactEncoding for Ipv6Addr {
951990 fn encoded_size ( & self ) -> std:: result:: Result < usize , EncodingError > {
952- Ok ( 4 )
991+ Ok ( IPV6_ADDR_ENCODED_SIZE )
953992 }
954993
994+ /// ```
995+ /// # use std::net::Ipv6Addr;
996+ /// # use compact_encoding::CompactEncoding;
997+ /// let addr: Ipv6Addr = "1:2:3::1".parse()?;
998+ /// let buff = addr.to_encoded_bytes()?.to_vec();
999+ /// assert_eq!(buff, vec![0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
1000+ /// # Ok::<(), Box<dyn std::error::Error>>(())
1001+ /// ```
9551002 fn encode < ' a > ( & self , buffer : & ' a mut [ u8 ] ) -> std:: result:: Result < & ' a mut [ u8 ] , EncodingError > {
9561003 let Some ( ( dest, rest) ) = buffer. split_first_chunk_mut :: < 16 > ( ) else {
9571004 return Err ( EncodingError :: out_of_bounds ( & format ! (
@@ -1016,6 +1063,14 @@ impl<T: VecEncodable> CompactEncoding for Vec<T> {
10161063 }
10171064}
10181065
1066+ /// Get the encoded size for a Vec with elements which have a fixed size encoding.
1067+ pub fn vec_encoded_size_for_fixed_sized_elements < T : CompactEncoding > (
1068+ vec : & [ T ] ,
1069+ element_encoded_size : usize ,
1070+ ) -> usize {
1071+ encoded_size_usize ( vec. len ( ) ) + ( vec. len ( ) * element_encoded_size)
1072+ }
1073+
10191074impl VecEncodable for u32 {
10201075 fn vec_encoded_size ( vec : & [ Self ] ) -> Result < usize , EncodingError >
10211076 where
@@ -1107,6 +1162,86 @@ impl<T: BoxedSliceEncodable> CompactEncoding for Box<[T]> {
11071162 }
11081163}
11091164
1165+ impl CompactEncoding for SocketAddrV4 {
1166+ fn encoded_size ( & self ) -> Result < usize , EncodingError > {
1167+ Ok ( SOCKET_ADDR_V4_ENCODED_SIZE )
1168+ }
1169+
1170+ /// ```
1171+ /// # use std::net::SocketAddrV4;
1172+ /// # use compact_encoding::CompactEncoding;
1173+ /// let addr: SocketAddrV4 = "127.0.0.1:42".parse()?;
1174+ /// let buff = addr.to_encoded_bytes()?.to_vec();
1175+ /// assert_eq!(buff, vec![127, 0, 0, 1, 42, 0]);
1176+ /// # Ok::<(), Box<dyn std::error::Error>>(())
1177+ /// ```
1178+ fn encode < ' a > ( & self , buffer : & ' a mut [ u8 ] ) -> Result < & ' a mut [ u8 ] , EncodingError > {
1179+ let rest = self . ip ( ) . encode ( buffer) ?;
1180+ encode_u16 ( self . port ( ) , rest)
1181+ }
1182+
1183+ fn decode ( buffer : & [ u8 ] ) -> Result < ( Self , & [ u8 ] ) , EncodingError >
1184+ where
1185+ Self : Sized ,
1186+ {
1187+ let ( ip, rest) = Ipv4Addr :: decode ( buffer) ?;
1188+ let ( port, rest) = decode_u16 ( rest) ?;
1189+ Ok ( ( SocketAddrV4 :: new ( ip, port) , rest) )
1190+ }
1191+ }
1192+ impl CompactEncoding for SocketAddrV6 {
1193+ fn encoded_size ( & self ) -> Result < usize , EncodingError > {
1194+ Ok ( SOCKET_ADDR_V6_ENCODED_SIZE )
1195+ }
1196+
1197+ /// ```
1198+ /// # use std::net::SocketAddrV6;
1199+ /// # use compact_encoding::CompactEncoding;
1200+ /// let addr: SocketAddrV6 = "[1:2:3::1]:80".parse()?;
1201+ /// let buff = addr.to_encoded_bytes()?.to_vec();
1202+ /// assert_eq!(buff, vec![0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 80, 0]);
1203+ /// # Ok::<(), Box<dyn std::error::Error>>(())
1204+ /// ```
1205+ fn encode < ' a > ( & self , buffer : & ' a mut [ u8 ] ) -> Result < & ' a mut [ u8 ] , EncodingError > {
1206+ let rest = self . ip ( ) . encode ( buffer) ?;
1207+ encode_u16 ( self . port ( ) , rest)
1208+ }
1209+
1210+ fn decode ( buffer : & [ u8 ] ) -> Result < ( Self , & [ u8 ] ) , EncodingError >
1211+ where
1212+ Self : Sized ,
1213+ {
1214+ let ( ip, rest) = Ipv6Addr :: decode ( buffer) ?;
1215+ let ( port, rest) = decode_u16 ( rest) ?;
1216+ // TODO is this correct for flowinfo and scope_id?
1217+ Ok ( ( SocketAddrV6 :: new ( ip, port, 0 , 0 ) , rest) )
1218+ }
1219+ }
1220+
1221+ impl VecEncodable for SocketAddrV4 {
1222+ fn vec_encoded_size ( vec : & [ Self ] ) -> Result < usize , EncodingError >
1223+ where
1224+ Self : Sized ,
1225+ {
1226+ Ok ( vec_encoded_size_for_fixed_sized_elements (
1227+ vec,
1228+ SOCKET_ADDR_V4_ENCODED_SIZE ,
1229+ ) )
1230+ }
1231+ }
1232+
1233+ impl VecEncodable for SocketAddrV6 {
1234+ fn vec_encoded_size ( vec : & [ Self ] ) -> Result < usize , EncodingError >
1235+ where
1236+ Self : Sized ,
1237+ {
1238+ Ok ( vec_encoded_size_for_fixed_sized_elements (
1239+ vec,
1240+ SOCKET_ADDR_V6_ENCODED_SIZE ,
1241+ ) )
1242+ }
1243+ }
1244+
11101245#[ cfg( test) ]
11111246mod test {
11121247 use super :: * ;
0 commit comments