@@ -141,13 +141,20 @@ impl Key {
141141 ///
142142 /// See [`ensure_max_length`] for details on the shortening algorithm.
143143 pub fn shortened_to_valid_length (
144- prefix : impl Into < String > ,
144+ prefix : Option < & str > ,
145145 name : impl Into < String > ,
146146 ) -> Result < Self , KeyError > {
147- let prefix = ensure_max_length ( prefix, KEY_PREFIX_MAX_LEN , 8 ) ;
147+ // Note that we are *not* shortening the prefix: If it isn't already a valid DNS subdomain
148+ // name, shortening won't make it one. In particular, a prefix must end in a letters-only
149+ // TLD, but the appended hash adds a hyphen and probably digits, very likely being an
150+ // invalid result.
148151 let name = ensure_max_length ( name, KEY_NAME_MAX_LEN , 8 ) ;
149152
150- Self :: from_str ( & format ! ( "{prefix}/{name}" ) )
153+ let key = match prefix {
154+ Some ( prefix) => format ! ( "{prefix}/{name}" ) ,
155+ None => name,
156+ } ;
157+ Self :: from_str ( & key)
151158 }
152159
153160 /// Retrieves the key's prefix.
@@ -377,6 +384,60 @@ mod test {
377384 assert_eq ! ( key. to_string( ) , "vendor" ) ;
378385 }
379386
387+ #[ test]
388+ fn key_shortened_to_valid_length_with_short_enough_name ( ) {
389+ let key = Key :: shortened_to_valid_length ( Some ( "stackable.tech" ) , "a" . repeat ( 63 ) ) . unwrap ( ) ;
390+
391+ assert_eq ! ( key. prefix, Some ( KeyPrefix ( "stackable.tech" . into( ) ) ) ) ;
392+ assert_eq ! ( key. name, KeyName ( "a" . repeat( 63 ) ) ) ;
393+ assert_eq ! ( key. name. len( ) , KEY_NAME_MAX_LEN ) ;
394+ assert_eq ! (
395+ key. to_string( ) ,
396+ "stackable.tech/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
397+ ) ;
398+ }
399+
400+ #[ test]
401+ fn key_shortened_to_valid_length_with_too_long_name ( ) {
402+ let key = Key :: shortened_to_valid_length ( Some ( "stackable.tech" ) , "a" . repeat ( 64 ) ) . unwrap ( ) ;
403+
404+ assert_eq ! ( key. prefix, Some ( KeyPrefix ( "stackable.tech" . into( ) ) ) ) ;
405+ assert_eq ! ( key. name, KeyName ( format!( "{}-ffe054fe" , "a" . repeat( 54 ) ) ) ) ;
406+ assert_eq ! ( key. name. len( ) , KEY_NAME_MAX_LEN ) ;
407+ assert_eq ! (
408+ key. to_string( ) ,
409+ "stackable.tech/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ffe054fe"
410+ ) ;
411+ }
412+
413+ #[ test]
414+ fn key_shortened_to_valid_length_with_too_long_prefix ( ) {
415+ // The prefix is a valid DNS subdomain name, except for being one character too long.
416+ let prefix = format ! ( "{}.tech" , "a" . repeat( 249 ) ) ;
417+ let error = Key :: shortened_to_valid_length ( Some ( & prefix) , "myname" )
418+ . expect_err ( "the prefix exceeds the maximum length" ) ;
419+
420+ assert_eq ! (
421+ error,
422+ KeyError :: KeyPrefixError {
423+ source: KeyPrefixError :: PrefixTooLong { length: 254 }
424+ }
425+ ) ;
426+ }
427+
428+ #[ test]
429+ fn key_shortened_to_valid_length_without_prefix ( ) {
430+ let key = Key :: shortened_to_valid_length ( None , "a" . repeat ( 64 ) ) . unwrap ( ) ;
431+
432+ assert_eq ! ( key. prefix, None ) ;
433+ assert_eq ! ( key. name, KeyName ( format!( "{}-ffe054fe" , "a" . repeat( 54 ) ) ) ) ;
434+ assert_eq ! ( key. name. len( ) , KEY_NAME_MAX_LEN ) ;
435+ assert_eq ! (
436+ key. to_string( ) ,
437+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ffe054fe"
438+ ) ;
439+ }
440+
380441 #[ test]
381442 fn prefix_equality ( ) {
382443 const EXAMPLE_PREFIX_STR : & str = "stackable.tech" ;
0 commit comments