@@ -426,22 +426,8 @@ pub(crate) enum Identifier<'s> {
426426}
427427
428428impl < ' i , ' s > LexWith < ' i , & ' s Scheme > for Identifier < ' s > {
429- fn lex_with ( mut input : & ' i str , scheme : & ' s Scheme ) -> LexResult < ' i , Self > {
430- let initial_input = input;
431-
432- loop {
433- input = take_while ( input, "identifier character" , |c| {
434- c. is_ascii_alphanumeric ( ) || c == '_'
435- } ) ?
436- . 1 ;
437-
438- match expect ( input, "." ) {
439- Ok ( rest) => input = rest,
440- Err ( _) => break ,
441- } ;
442- }
443-
444- let name = span ( initial_input, input) ;
429+ fn lex_with ( input : & ' i str , scheme : & ' s Scheme ) -> LexResult < ' i , Self > {
430+ let ( name, input) = lex_identifier_name ( input) ?;
445431
446432 let field = scheme
447433 . get ( name)
@@ -451,6 +437,25 @@ impl<'i, 's> LexWith<'i, &'s Scheme> for Identifier<'s> {
451437 }
452438}
453439
440+ #[ inline]
441+ fn lex_identifier_name ( mut input : & str ) -> LexResult < ' _ , & str > {
442+ let initial_input = input;
443+
444+ loop {
445+ input = take_while ( input, "identifier character" , |c| {
446+ c. is_ascii_alphanumeric ( ) || c == '_'
447+ } ) ?
448+ . 1 ;
449+
450+ match expect ( input, "." ) {
451+ Ok ( rest) => input = rest,
452+ Err ( _) => break ,
453+ } ;
454+ }
455+
456+ Ok ( ( span ( initial_input, input) , input) )
457+ }
458+
454459/// An error that occurs if an unregistered field name was queried from a
455460/// [`Scheme`](struct@Scheme).
456461#[ derive( Debug , PartialEq , Eq , Error ) ]
@@ -485,6 +490,28 @@ pub enum IdentifierRedefinitionError {
485490 Function ( #[ source] FunctionRedefinitionError ) ,
486491}
487492
493+ /// An error that occurs when registering a field or function identifier.
494+ #[ derive( Debug , PartialEq , Eq , Error ) ]
495+ pub enum IdentifierRegistrationError {
496+ /// The identifier does not follow the syntax accepted for registration.
497+ #[ error( "invalid identifier {0}" ) ]
498+ InvalidIdentifier ( String ) ,
499+
500+ /// The identifier is already registered as a field or function.
501+ #[ error( "{0}" ) ]
502+ Redefinition ( #[ from] IdentifierRedefinitionError ) ,
503+ }
504+
505+ fn is_valid_identifier ( name : & str ) -> bool {
506+ matches ! ( lex_identifier_name( name) , Ok ( ( _, "" ) ) )
507+ && matches ! ( name. as_bytes( ) . first( ) , Some ( b) if b. is_ascii_alphabetic( ) || * b == b'_' )
508+ && name. split ( '.' ) . all ( |segment| {
509+ segment
510+ . bytes ( )
511+ . any ( |b| b. is_ascii_alphabetic ( ) || b == b'_' )
512+ } )
513+ }
514+
488515#[ derive( Clone , Copy , Debug ) ]
489516enum SchemeItem {
490517 Field ( usize ) ,
@@ -647,16 +674,23 @@ impl SchemeBuilder {
647674 name : Arc < str > ,
648675 ty : Type ,
649676 optional : bool ,
650- ) -> Result < ( ) , IdentifierRedefinitionError > {
677+ ) -> Result < ( ) , IdentifierRegistrationError > {
678+ if !is_valid_identifier ( & name) {
679+ return Err ( IdentifierRegistrationError :: InvalidIdentifier (
680+ name. to_string ( ) ,
681+ ) ) ;
682+ }
683+
651684 match self . items . entry ( name) {
652- Entry :: Occupied ( entry) => match entry. get ( ) {
653- SchemeItem :: Field ( _) => Err ( IdentifierRedefinitionError :: Field (
654- FieldRedefinitionError ( entry. key ( ) . to_string ( ) ) ,
685+ Entry :: Occupied ( entry) => Err ( match entry. get ( ) {
686+ SchemeItem :: Field ( _) => IdentifierRedefinitionError :: Field ( FieldRedefinitionError (
687+ entry. key ( ) . to_string ( ) ,
655688 ) ) ,
656- SchemeItem :: Function ( _) => Err ( IdentifierRedefinitionError :: Function (
689+ SchemeItem :: Function ( _) => IdentifierRedefinitionError :: Function (
657690 FunctionRedefinitionError ( entry. key ( ) . to_string ( ) ) ,
658- ) ) ,
659- } ,
691+ ) ,
692+ }
693+ . into ( ) ) ,
660694 Entry :: Vacant ( entry) => {
661695 let index = self . fields . len ( ) ;
662696 self . fields . push ( FieldDefinition {
@@ -675,7 +709,7 @@ impl SchemeBuilder {
675709 & mut self ,
676710 name : N ,
677711 ty : Type ,
678- ) -> Result < ( ) , IdentifierRedefinitionError > {
712+ ) -> Result < ( ) , IdentifierRegistrationError > {
679713 self . add_field_full ( name. as_ref ( ) . into ( ) , ty, false )
680714 }
681715
@@ -684,7 +718,7 @@ impl SchemeBuilder {
684718 & mut self ,
685719 name : N ,
686720 ty : Type ,
687- ) -> Result < ( ) , IdentifierRedefinitionError > {
721+ ) -> Result < ( ) , IdentifierRegistrationError > {
688722 self . add_field_full ( name. as_ref ( ) . into ( ) , ty, true )
689723 }
690724
@@ -693,16 +727,24 @@ impl SchemeBuilder {
693727 & mut self ,
694728 name : N ,
695729 function : impl FunctionDefinition + ' static ,
696- ) -> Result < ( ) , IdentifierRedefinitionError > {
697- match self . items . entry ( name. as_ref ( ) . into ( ) ) {
698- Entry :: Occupied ( entry) => match entry. get ( ) {
699- SchemeItem :: Field ( _) => Err ( IdentifierRedefinitionError :: Field (
700- FieldRedefinitionError ( entry. key ( ) . to_string ( ) ) ,
730+ ) -> Result < ( ) , IdentifierRegistrationError > {
731+ let name = name. as_ref ( ) ;
732+ if !is_valid_identifier ( name) {
733+ return Err ( IdentifierRegistrationError :: InvalidIdentifier (
734+ name. to_string ( ) ,
735+ ) ) ;
736+ }
737+
738+ match self . items . entry ( name. into ( ) ) {
739+ Entry :: Occupied ( entry) => Err ( match entry. get ( ) {
740+ SchemeItem :: Field ( _) => IdentifierRedefinitionError :: Field ( FieldRedefinitionError (
741+ entry. key ( ) . to_string ( ) ,
701742 ) ) ,
702- SchemeItem :: Function ( _) => Err ( IdentifierRedefinitionError :: Function (
743+ SchemeItem :: Function ( _) => IdentifierRedefinitionError :: Function (
703744 FunctionRedefinitionError ( entry. key ( ) . to_string ( ) ) ,
704- ) ) ,
705- } ,
745+ ) ,
746+ }
747+ . into ( ) ) ,
706748 Entry :: Vacant ( entry) => {
707749 let index = self . functions . len ( ) ;
708750 self . functions
@@ -1854,10 +1896,80 @@ fn test_field_type_override() {
18541896
18551897 assert_eq ! (
18561898 builder. add_field( "foo" , Type :: Bytes ) ,
1857- Err ( IdentifierRedefinitionError :: Field ( FieldRedefinitionError (
1858- "foo" . into( )
1859- ) ) )
1899+ Err ( IdentifierRegistrationError :: Redefinition (
1900+ IdentifierRedefinitionError :: Field ( FieldRedefinitionError ( "foo" . into( ) ) )
1901+ ) )
1902+ ) ;
1903+ }
1904+
1905+ #[ test]
1906+ fn test_identifier_registration ( ) {
1907+ use crate :: ConcatFunction ;
1908+
1909+ let mut builder = SchemeBuilder :: new ( ) ;
1910+ let valid_field_names = [
1911+ "_" ,
1912+ "field" ,
1913+ "Field_0" ,
1914+ "http._request" ,
1915+ "a.b2._c3" ,
1916+ "cf.response.1xxx_code" ,
1917+ ] ;
1918+ for name in valid_field_names {
1919+ assert_eq ! ( builder. add_field( name, Type :: Bytes ) , Ok ( ( ) ) ) ;
1920+ }
1921+ assert_eq ! (
1922+ builder. add_optional_field( "optional.field" , Type :: Int ) ,
1923+ Ok ( ( ) )
1924+ ) ;
1925+ assert_eq ! (
1926+ builder. add_function( "function.name" , ConcatFunction :: new( ) ) ,
1927+ Ok ( ( ) )
1928+ ) ;
1929+
1930+ for name in [
1931+ "" ,
1932+ ".field" ,
1933+ "field." ,
1934+ "field..name" ,
1935+ "0field" ,
1936+ "123" ,
1937+ "192.0.2.1" ,
1938+ "a.1" ,
1939+ "a.123" ,
1940+ "a.1.2" ,
1941+ "f-ield" ,
1942+ "féield" ,
1943+ ] {
1944+ assert_eq ! (
1945+ builder. add_field( name, Type :: Bytes ) ,
1946+ Err ( IdentifierRegistrationError :: InvalidIdentifier ( name. into( ) ) )
1947+ ) ;
1948+ }
1949+
1950+ assert_eq ! (
1951+ builder. add_optional_field( "optional." , Type :: Int ) ,
1952+ Err ( IdentifierRegistrationError :: InvalidIdentifier (
1953+ "optional." . into( )
1954+ ) )
1955+ ) ;
1956+ assert_eq ! (
1957+ builder. add_function( "1function" , ConcatFunction :: new( ) ) ,
1958+ Err ( IdentifierRegistrationError :: InvalidIdentifier (
1959+ "1function" . into( )
1960+ ) )
18601961 ) ;
1962+
1963+ let scheme = builder. build ( ) ;
1964+ for name in valid_field_names. into_iter ( ) . chain ( [ "optional.field" ] ) {
1965+ let ( field, rest) = FieldRef :: lex_with ( name, & scheme) . unwrap ( ) ;
1966+ assert_eq ! ( field. name( ) , name) ;
1967+ assert_eq ! ( rest, "" ) ;
1968+ }
1969+
1970+ let ( function, rest) = FunctionRef :: lex_with ( "function.name" , & scheme) . unwrap ( ) ;
1971+ assert_eq ! ( function. name( ) , "function.name" ) ;
1972+ assert_eq ! ( rest, "" ) ;
18611973}
18621974
18631975#[ test]
@@ -1920,6 +2032,17 @@ fn test_scheme_json_serialization() {
19202032 assert_eq ! ( scheme. inner. fields, new_scheme. inner. fields) ;
19212033}
19222034
2035+ #[ test]
2036+ fn test_scheme_json_rejects_invalid_identifier ( ) {
2037+ let scheme = Scheme ! { valid: Int } . build ( ) ;
2038+ let json = serde_json:: to_string ( & scheme)
2039+ . unwrap ( )
2040+ . replace ( "\" valid\" " , "\" 1invalid\" " ) ;
2041+
2042+ let err = serde_json:: from_str :: < Scheme > ( & json) . unwrap_err ( ) ;
2043+ assert ! ( err. to_string( ) . contains( "invalid identifier 1invalid" ) ) ;
2044+ }
2045+
19232046#[ test]
19242047fn test_nil_not_equal_behavior_true ( ) {
19252048 use crate :: { Array , ExecutionContext , Map } ;
0 commit comments