@@ -915,103 +915,67 @@ impl Readable for String {
915
915
}
916
916
}
917
917
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.
921
919
/// This serialization is used by BOLT 7 hostnames.
922
920
#[ 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 .
926
924
pub fn len ( & self ) -> u8 {
927
925
( & self . 0 ) . len ( ) as u8
928
926
}
929
927
}
930
- impl Deref for Hostname {
928
+ impl Deref for ShortAsciiString {
931
929
type Target = String ;
932
930
933
931
fn deref ( & self ) -> & Self :: Target {
934
932
& self . 0
935
933
}
936
934
}
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 {
939
937
short_s. 0
940
938
}
941
939
}
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 = ( ) ;
959
942
960
943
fn try_from ( bytes : Vec < u8 > ) -> Result < Self , Self :: Error > {
961
944
if let Ok ( s) = String :: from_utf8 ( bytes) {
962
- Hostname :: try_from ( s)
945
+ ShortAsciiString :: try_from ( s)
963
946
} else {
964
- Err ( HostnameConversionError :: InvalidChar )
947
+ Err ( ( ) )
965
948
}
966
949
}
967
950
}
968
- impl TryFrom < String > for Hostname {
969
- type Error = HostnameConversionError ;
951
+ impl TryFrom < String > for ShortAsciiString {
952
+ type Error = ( ) ;
970
953
971
954
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 ( ( ) )
974
961
}
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) )
998
962
}
999
963
}
1000
- impl Writeable for Hostname {
964
+ impl Writeable for ShortAsciiString {
1001
965
#[ inline]
1002
966
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1003
967
self . len ( ) . write ( w) ?;
1004
968
w. write_all ( self . as_bytes ( ) )
1005
969
}
1006
970
}
1007
- impl Readable for Hostname {
971
+ impl Readable for ShortAsciiString {
1008
972
#[ inline]
1009
- fn read < R : Read > ( r : & mut R ) -> Result < Hostname , DecodeError > {
973
+ fn read < R : Read > ( r : & mut R ) -> Result < ShortAsciiString , DecodeError > {
1010
974
let len: u8 = Readable :: read ( r) ?;
1011
975
let mut vec = Vec :: with_capacity ( len. into ( ) ) ;
1012
976
vec. resize ( len. into ( ) , 0 ) ;
1013
977
r. read_exact ( & mut vec) ?;
1014
- Hostname :: try_from ( vec) . map_err ( |_| DecodeError :: InvalidValue )
978
+ ShortAsciiString :: try_from ( vec) . map_err ( |_| DecodeError :: InvalidValue )
1015
979
}
1016
980
}
1017
981
@@ -1034,30 +998,23 @@ impl Readable for Duration {
1034
998
#[ cfg( test) ]
1035
999
mod tests {
1036
1000
use core:: convert:: TryFrom ;
1037
- use util:: ser:: { Readable , Hostname , Writeable } ;
1001
+ use util:: ser:: { Readable , ShortAsciiString , Writeable } ;
1038
1002
1039
1003
#[ 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( ) ) ;
1051
1008
let mut large_vec = Vec :: with_capacity ( 256 ) ;
1052
1009
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( ) ) ;
1054
1011
}
1055
1012
1056
1013
#[ 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 ( ) ;
1059
1016
let mut buf: Vec < u8 > = Vec :: new ( ) ;
1060
1017
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" ) ;
1062
1019
}
1063
1020
}
0 commit comments