@@ -102,6 +102,12 @@ type RangeErrorDetails struct {
102102}
103103
104104func (r RangeErrorDetails ) Error () string {
105+ if r .Max == math .MaxInt64 || r .Max < 0 {
106+ return fmt .Sprintf ("%d < %d" , r .Actual , r .Min )
107+ }
108+ if r .Min == math .MinInt64 || r .Min < 0 {
109+ return fmt .Sprintf ("%d > %d" , r .Actual , r .Max )
110+ }
105111 return fmt .Sprintf ("%d != [%d , %d]" , r .Actual , r .Min , r .Max )
106112}
107113
@@ -170,6 +176,7 @@ const (
170176 TupleSchemeName = "TupleScheme"
171177 TupleSchemeNamedName = "TupleSchemeNamed"
172178 SRepeatSchemeName = "SRepeatScheme"
179+ SchemeMapRepeatName = "SchemeMapRepeat"
173180)
174181
175182type SchemeGeneric struct {
@@ -1798,8 +1805,12 @@ func (s SRepeatScheme) Validate(seq *access.SeqGetAccess) error {
17981805 argCount := seq .ArgCount () - pos
17991806
18001807 if s .min != - 1 && argCount < s .min {
1801- return NewSchemeError (ErrConstraintViolated , SRepeatSchemeName , "" , pos ,
1802- fmt .Errorf ("expected minimum %d elements, but only %d remain" , s .min , argCount ))
1808+ return NewSchemeError (ErrConstraintViolated , SRepeatSchemeName , "" , pos , RangeErrorDetails {
1809+ Min : int64 (s .min ),
1810+ Max : int64 (s .max ),
1811+ Actual : int64 (argCount ),
1812+ })
1813+
18031814 }
18041815
18051816 maxIter := argCount
@@ -1829,7 +1840,11 @@ func (s SRepeatScheme) Decode(seq *access.SeqGetAccess) (any, error) {
18291840
18301841 if s .min != - 1 && argCount < s .min {
18311842 return nil , NewSchemeError (ErrConstraintViolated , SRepeatSchemeName , "" , pos ,
1832- fmt .Errorf ("expected minimum %d elements, but only %d remain" , s .min , argCount ))
1843+ RangeErrorDetails {
1844+ Min : int64 (s .min ),
1845+ Max : int64 (s .max ),
1846+ Actual : int64 (argCount ),
1847+ })
18331848 }
18341849
18351850 maxIter := argCount
@@ -1864,8 +1879,11 @@ func (s SRepeatScheme) Encode(put *access.PutAccess, val any) error {
18641879 }
18651880 argCount := len (valArr )
18661881 if s .min != - 1 && argCount < s .min {
1867- return NewSchemeError (ErrConstraintViolated , SRepeatSchemeName , "" , - 1 ,
1868- fmt .Errorf ("expected minimum %d elements, but only %d remain" , s .min , argCount ))
1882+ return NewSchemeError (ErrConstraintViolated , SRepeatSchemeName , "" , - 1 , RangeErrorDetails {
1883+ Min : int64 (s .min ),
1884+ Max : int64 (s .max ),
1885+ Actual : int64 (argCount ),
1886+ })
18691887 }
18701888 maxIter := argCount
18711889 if s .max != - 1 && s .max < argCount {
@@ -1907,63 +1925,43 @@ func (s SchemeMultiCheckNamesScheme) IsNullable() bool {
19071925
19081926func (s SchemeMultiCheckNamesScheme ) Validate (seq * access.SeqGetAccess ) error {
19091927 pos := seq .CurrentIndex ()
1910- _ , err := precheck (SchemeMultiCheckNamesSchemeNamed , pos , seq , types .TypeTuple , - 1 , s .IsNullable ())
1911- if err != nil {
1912- return err
1913- }
1914- sub , err := seq .PeekNestedSeq ()
1928+ byteCount := (len (s .FieldNames ) + 7 ) / 8
1929+
1930+ // Direct primitive validation: expect a bytes value of exact width
1931+ err := validatePrimitive (SchemeBytesName , seq , types .TypeString , byteCount , s .IsNullable ())
19151932 if err != nil {
19161933 return NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
19171934 }
1918- if sub .ArgCount () != len (s .FieldNames ) {
1919- return NewSchemeError (ErrConstraintViolated , SchemeMultiCheckNamesSchemeNamed , "" , pos ,
1920- SizeExact {Actual : sub .ArgCount (), Exact : len (s .FieldNames )})
1921- }
1922- for range s .FieldNames {
1923- err := SchemeBool {}.Validate (sub )
1924- if err != nil {
1925- return NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1926- }
1927- }
1928- if err := seq .Advance (); err != nil {
1929- return NewSchemeError (ErrUnexpectedEOF , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1930- }
1935+
19311936 return nil
19321937}
19331938
19341939func (s SchemeMultiCheckNamesScheme ) Decode (seq * access.SeqGetAccess ) (any , error ) {
19351940 pos := seq .CurrentIndex ()
1936- _ , err := precheck (SchemeMultiCheckNamesSchemeNamed , pos , seq , types .TypeTuple , - 1 , s .IsNullable ())
1937- if err != nil {
1938- return nil , err
1939- }
1940-
1941- selected := make ([]string , 0 )
1941+ byteCount := (len (s .FieldNames ) + 7 ) / 8
19421942
1943- sub , err := seq . PeekNestedSeq ( )
1943+ payload , err := validatePrimitiveAndGetPayload ( SchemeMultiCheckNamesSchemeNamed , seq , types . TypeByteArray , byteCount , s . IsNullable () )
19441944 if err != nil {
19451945 return nil , NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
19461946 }
1947- if sub . ArgCount () != len ( s . FieldNames ) {
1948- return nil , NewSchemeError ( ErrConstraintViolated , SchemeMultiCheckNamesSchemeNamed , "" , pos ,
1949- SizeExact { Actual : sub . ArgCount (), Exact : len ( s . FieldNames )})
1950- }
1947+ if payload == nil {
1948+ if s . Nullable {
1949+ return nil , nil // allow nullable
1950+ } else {
19511951
1952- for _ , name := range s .FieldNames {
1953- v , err := SchemeBool {}.Decode (sub )
1954- if err != nil {
1955- return nil , NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , name , pos , err )
1956- }
1957- if b , ok := v .(bool ); ok && b {
1958- selected = append (selected , name )
1952+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , nil )
19591953 }
19601954 }
19611955
1962- if err := seq .Advance (); err != nil {
1963- return nil , NewSchemeError (ErrUnexpectedEOF , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1956+ selected := make ([]string , 0 )
1957+ for i , name := range s .FieldNames {
1958+ byteIndex := i / 8
1959+ bitIndex := uint (i % 8 )
1960+ if payload [byteIndex ]& (1 << bitIndex ) != 0 {
1961+ selected = append (selected , name )
1962+ }
19641963 }
19651964
1966- // Return only the slice of selected names
19671965 return selected , nil
19681966}
19691967
@@ -1987,16 +1985,17 @@ func (s SchemeMultiCheckNamesScheme) Encode(put *access.PutAccess, val any) erro
19871985 return NewSchemeError (ErrEncode , SchemeMultiCheckNamesSchemeNamed , "" , - 1 , ErrTypeMisMatch )
19881986 }
19891987
1990- nested := put . BeginTuple ()
1991- defer put . EndNested ( nested )
1988+ byteCount := ( len ( s . FieldNames ) + 7 ) / 8
1989+ buf := make ([] byte , byteCount )
19921990
1993- for _ , key := range s .FieldNames {
1994- _ , checked := set [key ]
1995- err := SchemeBool {}. Encode ( nested , checked )
1996- if err != nil {
1997- return NewSchemeError ( ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , key , - 1 , err )
1991+ for i , key := range s .FieldNames {
1992+ if _ , ok := set [key ]; ok {
1993+ byteIndex := i / 8
1994+ bitIndex := uint ( i % 8 )
1995+ buf [ byteIndex ] |= 1 << bitIndex
19981996 }
19991997 }
1998+ put .AddBytes (buf )
20001999 return nil
20012000}
20022001
@@ -2197,3 +2196,150 @@ func SColor(nullable bool) Scheme {
21972196 }
21982197 return s .Pattern (`^#(?:[0-9a-fA-F]{3}){1,2}$` )
21992198}
2199+
2200+ type SchemeMapRepeat struct {
2201+ Key Scheme
2202+ Value Scheme
2203+ min int
2204+ max int
2205+ }
2206+
2207+ func SMapRepeat (key Scheme , value Scheme ) SchemeMapRepeat {
2208+ return SchemeMapRepeat {Key : key , Value : value , min : - 1 , max : - 1 }
2209+ }
2210+
2211+ func SMapRepeatRange (key Scheme , value Scheme , min , max int ) SchemeMapRepeat {
2212+ return SchemeMapRepeat {Key : key , Value : value , min : min , max : max }
2213+ }
2214+
2215+ func (s SchemeMapRepeat ) IsNullable () bool {
2216+ return s .min <= 0
2217+ }
2218+
2219+ func (s SchemeMapRepeat ) Validate (seq * access.SeqGetAccess ) error {
2220+ pos := seq .CurrentIndex ()
2221+ _ , err := precheck (SchemeMapRepeatName , pos , seq , types .TypeMap , - 1 , s .IsNullable ())
2222+ if err != nil {
2223+ return err
2224+ }
2225+ subseq , err := seq .PeekNestedSeq ()
2226+ if err != nil {
2227+ return NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos , err )
2228+ }
2229+ pairCount := subseq .ArgCount () / 2
2230+ maxIter := pairCount
2231+ if s .max != - 1 && s .max < pairCount {
2232+ maxIter = s .max
2233+ }
2234+ if s .min != - 1 && pairCount < s .min {
2235+ return NewSchemeError (ErrConstraintViolated , SchemeMapRepeatName , "" , pos ,
2236+ RangeErrorDetails {
2237+ Min : int64 (s .min ),
2238+ Max : int64 (s .max ),
2239+ Actual : int64 (pairCount ),
2240+ })
2241+ }
2242+
2243+ for i := 0 ; i < maxIter ; i ++ {
2244+
2245+ if err := s .Key .Validate (subseq ); err != nil {
2246+ return NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos , err )
2247+ }
2248+ if err := s .Value .Validate (subseq ); err != nil {
2249+ return NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos , err )
2250+ }
2251+ }
2252+
2253+ if err := seq .Advance (); err != nil {
2254+ return NewSchemeError (ErrUnexpectedEOF , SchemeMapRepeatName , "" , pos , err )
2255+ }
2256+ return nil
2257+ }
2258+
2259+ func (s SchemeMapRepeat ) Decode (seq * access.SeqGetAccess ) (any , error ) {
2260+ pos := seq .CurrentIndex ()
2261+ _ , err := precheck (SchemeMapRepeatName , pos , seq , types .TypeMap , 0 , s .IsNullable ())
2262+ if err != nil {
2263+ return nil , err
2264+ }
2265+ subseq , err := seq .PeekNestedSeq ()
2266+ if err != nil {
2267+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos , err )
2268+ }
2269+ pairCount := subseq .ArgCount () / 2
2270+ maxIter := pairCount
2271+ if s .max != - 1 && s .max < pairCount {
2272+ maxIter = s .max
2273+ }
2274+ if s .min != - 1 && pairCount < s .min {
2275+ return nil , NewSchemeError (ErrConstraintViolated , SchemeMapRepeatName , "" , pos ,
2276+ RangeErrorDetails {
2277+ Min : int64 (s .min ),
2278+ Max : int64 (s .max ),
2279+ Actual : int64 (pairCount ),
2280+ })
2281+ }
2282+ out := make (map [string ]any )
2283+ for i := 0 ; i < maxIter ; i ++ {
2284+ k , err := s .Key .Decode (subseq )
2285+ if err != nil {
2286+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos , err )
2287+ }
2288+ v , err := s .Value .Decode (subseq )
2289+ if err != nil {
2290+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos , err )
2291+ }
2292+ if keyStr , ok := k .(string ); ok {
2293+ out [keyStr ] = v
2294+ } else {
2295+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMapRepeatName , "" , pos - 1 , ErrUnsupportedType )
2296+ }
2297+ }
2298+
2299+ if err := seq .Advance (); err != nil {
2300+ return nil , NewSchemeError (ErrUnexpectedEOF , SchemeMapRepeatName , "" , pos , err )
2301+ }
2302+ return out , nil
2303+ }
2304+
2305+ func (s SchemeMapRepeat ) Encode (put * access.PutAccess , val any ) error {
2306+ mapKV , ok := val .(map [string ]any )
2307+ if ! ok {
2308+ return NewSchemeError (ErrEncode , SchemeMapRepeatName , "" , - 1 , ErrTypeMisMatch )
2309+ }
2310+
2311+ nested := put .BeginMap ()
2312+ defer put .EndNested (nested )
2313+
2314+ count := 0
2315+ for key , v := range mapKV {
2316+ // Encode key
2317+ if err := s .Key .Encode (nested , key ); err != nil {
2318+ return NewSchemeError (ErrEncode , SchemeMapRepeatName , key , - 1 , err )
2319+ }
2320+ // Encode value
2321+ if err := s .Value .Encode (nested , v ); err != nil {
2322+ return NewSchemeError (ErrEncode , SchemeMapRepeatName , key , - 1 , err )
2323+ }
2324+ count ++
2325+ }
2326+
2327+ if s .min != - 1 && count < s .min {
2328+ return NewSchemeError (ErrConstraintViolated , SchemeMapRepeatName , "" , - 1 ,
2329+ RangeErrorDetails {
2330+ Min : int64 (s .min ),
2331+ Max : int64 (s .max ),
2332+ Actual : int64 (count ),
2333+ })
2334+ }
2335+ if s .max != - 1 && count > s .max {
2336+ return NewSchemeError (ErrConstraintViolated , SchemeMapRepeatName , "" , - 1 ,
2337+ RangeErrorDetails {
2338+ Min : int64 (s .min ),
2339+ Max : int64 (s .max ),
2340+ Actual : int64 (count ),
2341+ })
2342+ }
2343+
2344+ return nil
2345+ }
0 commit comments