@@ -915,103 +915,67 @@ impl Readable for String {
915915 }
916916}
917917
918- /// Represents a hostname with validation for serialization purposes.
919- /// The hostname follows the preferred form summarized in e.g. RFC 3696.
920- /// Its length is guaranteed to be representable by a single byte.
918+ /// Represents a printable ASCII string whose length can be represented by a single byte.
921919/// This serialization is used by BOLT 7 hostnames.
922920#[ derive( Clone , Debug , PartialEq ) ]
923- pub struct Hostname ( String ) ;
924- impl Hostname {
925- /// Returns the length of the hostname .
921+ pub struct ShortAsciiString ( String ) ;
922+ impl ShortAsciiString {
923+ /// Returns the length of the short ASCII string .
926924 pub fn len ( & self ) -> u8 {
927925 ( & self . 0 ) . len ( ) as u8
928926 }
929927}
930- impl Deref for Hostname {
928+ impl Deref for ShortAsciiString {
931929 type Target = String ;
932930
933931 fn deref ( & self ) -> & Self :: Target {
934932 & self . 0
935933 }
936934}
937- impl From < Hostname > for String {
938- fn from ( short_s : Hostname ) -> Self {
935+ impl From < ShortAsciiString > for String {
936+ fn from ( short_s : ShortAsciiString ) -> Self {
939937 short_s. 0
940938 }
941939}
942- /// An error returned when converting into a hostname.
943- /// This conversion follows the preferred form summarized in e.g. RFC 3696.
944- #[ derive( Debug ) ]
945- pub enum HostnameConversionError {
946- /// The hostname exceeded 255 bytes.
947- InvalidLength ,
948- /// A label exceeded 63 bytes.
949- InvalidLabelLength ,
950- /// A zero length root label was found without it being the last label.
951- InvalidRootLabel ,
952- /// An invalid character was found. Valid characters include only ASCII
953- /// alphanumeric characters and hyphens. Hyphens are invalid at the
954- /// beginning or end of a label.
955- InvalidChar ,
956- }
957- impl TryFrom < Vec < u8 > > for Hostname {
958- type Error = HostnameConversionError ;
940+ impl TryFrom < Vec < u8 > > for ShortAsciiString {
941+ type Error = ( ) ;
959942
960943 fn try_from ( bytes : Vec < u8 > ) -> Result < Self , Self :: Error > {
961944 if let Ok ( s) = String :: from_utf8 ( bytes) {
962- Hostname :: try_from ( s)
945+ ShortAsciiString :: try_from ( s)
963946 } else {
964- Err ( HostnameConversionError :: InvalidChar )
947+ Err ( ( ) )
965948 }
966949 }
967950}
968- impl TryFrom < String > for Hostname {
969- type Error = HostnameConversionError ;
951+ impl TryFrom < String > for ShortAsciiString {
952+ type Error = ( ) ;
970953
971954 fn try_from ( s : String ) -> Result < Self , Self :: Error > {
972- if s. len ( ) > 255 {
973- return Err ( HostnameConversionError :: InvalidLength ) ;
955+ if s. len ( ) <= 255 && s. chars ( ) . all ( |c|
956+ c. is_ascii ( ) && !c. is_ascii_control ( )
957+ ) {
958+ Ok ( ShortAsciiString ( s) )
959+ } else {
960+ Err ( ( ) )
974961 }
975- let mut labels = s. split ( '.' ) . enumerate ( ) . peekable ( ) ;
976- while let Some ( ( label_idx, label) ) = labels. next ( ) {
977- // Trailing zero length root label for fully-qualified name.
978- let last_label = labels. peek ( ) . is_none ( ) ;
979- if label. len ( ) == 0 {
980- if !last_label || label_idx == 0 {
981- return Err ( HostnameConversionError :: InvalidRootLabel ) ;
982- }
983- }
984- // Maximum label length from specification.
985- if label. len ( ) > 63 {
986- return Err ( HostnameConversionError :: InvalidLabelLength ) ;
987- }
988- for ( byte_idx, byte) in label. as_bytes ( ) . iter ( ) . enumerate ( ) {
989- if !byte. is_ascii_alphanumeric ( ) && * byte != b'-' {
990- return Err ( HostnameConversionError :: InvalidChar ) ;
991- }
992- if * byte == b'-' && ( byte_idx == 0 || byte_idx == label. len ( ) - 1 ) {
993- return Err ( HostnameConversionError :: InvalidChar ) ;
994- }
995- }
996- } ;
997- Ok ( Hostname ( s) )
998962 }
999963}
1000- impl Writeable for Hostname {
964+ impl Writeable for ShortAsciiString {
1001965 #[ inline]
1002966 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1003967 self . len ( ) . write ( w) ?;
1004968 w. write_all ( self . as_bytes ( ) )
1005969 }
1006970}
1007- impl Readable for Hostname {
971+ impl Readable for ShortAsciiString {
1008972 #[ inline]
1009- fn read < R : Read > ( r : & mut R ) -> Result < Hostname , DecodeError > {
973+ fn read < R : Read > ( r : & mut R ) -> Result < ShortAsciiString , DecodeError > {
1010974 let len: u8 = Readable :: read ( r) ?;
1011975 let mut vec = Vec :: with_capacity ( len. into ( ) ) ;
1012976 vec. resize ( len. into ( ) , 0 ) ;
1013977 r. read_exact ( & mut vec) ?;
1014- Hostname :: try_from ( vec) . map_err ( |_| DecodeError :: InvalidValue )
978+ ShortAsciiString :: try_from ( vec) . map_err ( |_| DecodeError :: InvalidValue )
1015979 }
1016980}
1017981
@@ -1034,30 +998,23 @@ impl Readable for Duration {
1034998#[ cfg( test) ]
1035999mod tests {
10361000 use core:: convert:: TryFrom ;
1037- use util:: ser:: { Readable , Hostname , Writeable } ;
1001+ use util:: ser:: { Readable , ShortAsciiString , Writeable } ;
10381002
10391003 #[ test]
1040- fn hostname_conversion ( ) {
1041- assert_eq ! ( Hostname :: try_from( String :: from( "test" ) ) . unwrap( ) . as_str( ) , "test" ) ;
1042- assert_eq ! ( Hostname :: try_from( String :: from( "test-1" ) ) . unwrap( ) . as_str( ) , "test-1" ) ;
1043- assert_eq ! ( Hostname :: try_from( String :: from( "1-test" ) ) . unwrap( ) . as_str( ) , "1-test" ) ;
1044- assert_eq ! ( Hostname :: try_from( String :: from( "test.com" ) ) . unwrap( ) . as_str( ) , "test.com" ) ;
1045- assert_eq ! ( Hostname :: try_from( String :: from( "test.com." ) ) . unwrap( ) . as_str( ) , "test.com." ) ;
1046- assert_eq ! ( Hostname :: try_from( String :: from( "a.test.com" ) ) . unwrap( ) . as_str( ) , "a.test.com" ) ;
1047-
1048- assert ! ( Hostname :: try_from( String :: from( "⚡" ) ) . is_err( ) ) ;
1049- assert ! ( Hostname :: try_from( String :: from( "-end" ) ) . is_err( ) ) ;
1050- assert ! ( Hostname :: try_from( String :: from( "start-" ) ) . is_err( ) ) ;
1004+ fn short_ascii_string_conversion ( ) {
1005+ assert_eq ! ( ShortAsciiString :: try_from( String :: from( "test" ) ) . unwrap( ) . as_str( ) , "test" ) ;
1006+
1007+ assert ! ( ShortAsciiString :: try_from( String :: from( "⚡" ) ) . is_err( ) ) ;
10511008 let mut large_vec = Vec :: with_capacity ( 256 ) ;
10521009 large_vec. resize ( 256 , b'A' ) ;
1053- assert ! ( Hostname :: try_from( String :: from_utf8( large_vec) . unwrap( ) ) . is_err( ) ) ;
1010+ assert ! ( ShortAsciiString :: try_from( String :: from_utf8( large_vec) . unwrap( ) ) . is_err( ) ) ;
10541011 }
10551012
10561013 #[ test]
1057- fn hostname_serialization ( ) {
1058- let short_s = Hostname :: try_from ( String :: from ( "test" ) ) . unwrap ( ) ;
1014+ fn short_ascii_string_serialization ( ) {
1015+ let short_s = ShortAsciiString :: try_from ( String :: from ( "test" ) ) . unwrap ( ) ;
10591016 let mut buf: Vec < u8 > = Vec :: new ( ) ;
10601017 short_s. write ( & mut buf) . unwrap ( ) ;
1061- assert_eq ! ( Hostname :: read( & mut buf. as_slice( ) ) . unwrap( ) . as_str( ) , "test" ) ;
1018+ assert_eq ! ( ShortAsciiString :: read( & mut buf. as_slice( ) ) . unwrap( ) . as_str( ) , "test" ) ;
10621019 }
10631020}
0 commit comments