@@ -62,9 +62,10 @@ pub trait Torus0Api<AccountId, Balance> {
6262/// This might have to increase in the future, but is a good enough default value.
6363/// If it ends up being formalized, the length can be described as a u8.
6464pub const MAX_NAMESPACE_PATH_LENGTH : usize = 256 ;
65- /// Number of total bytes a segment can contain.
66- pub const MAX_SEGMENT_LENGTH : usize = 64 ;
67- /// Max number of segments in a path.
65+ /// Number of total bytes a segment can contain. 63 plus dot.
66+ pub const MAX_SEGMENT_LENGTH : usize = 63 ;
67+ /// Max number of segments in a path. In the common prefix case, an agent will have
68+ /// up to 8 levels of depth to use, 2 being allocated to the agent prefix notation.
6869pub const MAX_NAMESPACE_SEGMENTS : usize = 10 ;
6970
7071pub const NAMESPACE_SEPARATOR : u8 = b'.' ;
@@ -103,19 +104,22 @@ impl NamespacePath {
103104 for segment in & segments {
104105 let segment = core:: str:: from_utf8 ( segment) . map_err ( |_| "path is invalid itf-8" ) ?;
105106
106- let first = segment. chars ( ) . next ( ) . ok_or ( "empty namespace segment" ) ?;
107- if !first. is_alphanumeric ( ) {
108- return Err ( "namespace segment must start with alphanumeric character" ) ;
109- }
110-
111107 if segment. len ( ) > MAX_SEGMENT_LENGTH {
112108 return Err ( "namespace segment too long" ) ;
113109 }
114110
115- if segment
116- . chars ( )
117- . any ( |c| !c. is_alphanumeric ( ) && c != '-' && c != '_' && c != '+' && c != '=' )
118- {
111+ let first = segment. chars ( ) . next ( ) . ok_or ( "empty namespace segment" ) ?;
112+ let last = segment. chars ( ) . last ( ) . ok_or ( "empty namespace segment" ) ?;
113+ if !first. is_ascii_alphanumeric ( ) || !last. is_ascii_alphanumeric ( ) {
114+ return Err ( "namespace segment must start and end with alphanumeric characters" ) ;
115+ }
116+
117+ if segment. chars ( ) . any ( |c| {
118+ !( c. is_ascii_digit ( ) || c. is_ascii_alphabetic ( ) && c. is_ascii_lowercase ( ) )
119+ && c != '-'
120+ && c != '_'
121+ && c != '+'
122+ } ) {
119123 return Err ( "invalid character in namespace segment" ) ;
120124 }
121125 }
@@ -224,17 +228,23 @@ mod tests {
224228 #[ test]
225229 fn namespace_creation_validates_paths ( ) {
226230 assert ! ( NamespacePath :: new_agent( b"agent.alice" ) . is_ok( ) ) ;
227- assert ! ( NamespacePath :: new_agent( "agent.alice.tørûs" . as_bytes( ) ) . is_ok( ) ) ;
228- assert ! ( NamespacePath :: new_agent( b"agent.alice_2.memory-1.key=val+1" ) . is_ok( ) ) ;
231+ assert ! ( NamespacePath :: new_agent( b"agent.alice_2.memory-1.func+1" ) . is_ok( ) ) ;
232+
233+ assert ! ( NamespacePath :: new_agent( format!( "agent.alice.{:0<63}" , 1 ) . as_bytes( ) ) . is_ok( ) ) ;
234+ assert ! ( NamespacePath :: new_agent( format!( "agent.alice.{:0<64}" , 1 ) . as_bytes( ) ) . is_err( ) ) ;
229235
230236 assert ! ( NamespacePath :: new_agent( b"" ) . is_err( ) ) ;
231237 assert ! ( NamespacePath :: new_agent( b"agent" ) . is_err( ) ) ;
232238 assert ! ( NamespacePath :: new_agent( b".agent" ) . is_err( ) ) ;
233239 assert ! ( NamespacePath :: new_agent( b"agent." ) . is_err( ) ) ;
240+ assert ! ( NamespacePath :: new_agent( b"agent.Alice" ) . is_err( ) ) ;
234241 assert ! ( NamespacePath :: new_agent( b"agent..alice" ) . is_err( ) ) ;
235242 assert ! ( NamespacePath :: new_agent( b"agent.-alice" ) . is_err( ) ) ;
243+ assert ! ( NamespacePath :: new_agent( b"agent.alice-" ) . is_err( ) ) ;
244+ assert ! ( NamespacePath :: new_agent( b"agent.-alice-" ) . is_err( ) ) ;
236245 assert ! ( NamespacePath :: new_agent( b"agent.alice!" ) . is_err( ) ) ;
237246 assert ! ( NamespacePath :: new_agent( b"agent.alice memory" ) . is_err( ) ) ;
247+ assert ! ( NamespacePath :: new_agent( "agent.alice.tørûs" . as_bytes( ) ) . is_err( ) ) ;
238248 }
239249
240250 #[ test]
0 commit comments