@@ -141,21 +141,22 @@ type Scheme interface {
141141}
142142
143143const (
144- SchemeAnyName = "SchemeAny"
145- SchemeStringName = "SchemeString"
146- SchemeBytesName = "SchemeBytes"
147- SchemeMapName = "SchemeMap"
148- SchemeTypeOnlyName = "SchemeTypeOnly"
149- SchemeBoolName = "SchemeBool"
150- SchemeInt8Name = "SchemeInt8"
151- SchemeInt16Name = "SchemeInt16"
152- SchemeInt32Name = "SchemeInt32"
153- SchemeInt64Name = "SchemeInt64"
154- SchemeFloat32Name = "SchemeFloat32"
155- SchemeFloat64Name = "SchemeFloat64"
156- SchemeNamedChainName = "SchemeNamedChain"
157- SchemeMapUnorderedName = "SchemeMapUnordered"
158- ChainName = "SchemeChain"
144+ SchemeAnyName = "SchemeAny"
145+ SchemeStringName = "SchemeString"
146+ SchemeBytesName = "SchemeBytes"
147+ SchemeMapName = "SchemeMap"
148+ SchemeTypeOnlyName = "SchemeTypeOnly"
149+ SchemeBoolName = "SchemeBool"
150+ SchemeInt8Name = "SchemeInt8"
151+ SchemeInt16Name = "SchemeInt16"
152+ SchemeInt32Name = "SchemeInt32"
153+ SchemeInt64Name = "SchemeInt64"
154+ SchemeFloat32Name = "SchemeFloat32"
155+ SchemeFloat64Name = "SchemeFloat64"
156+ SchemeNamedChainName = "SchemeNamedChain"
157+ SchemeMapUnorderedName = "SchemeMapUnordered"
158+ SchemeMultiCheckNamesSchemeNamed = "SchemeMultiCheckNamesSchemeNamed"
159+ ChainName = "SchemeChain"
159160
160161 TupleSchemeName = "TupleScheme"
161162 TupleSchemeNamedName = "TupleSchemeNamed"
@@ -1557,18 +1558,12 @@ type TupleSchemeNamed struct {
15571558}
15581559
15591560func STupleNamed (fieldNames []string , schema ... Scheme ) TupleSchemeNamed {
1560- if len (fieldNames ) != len (schema ) {
1561- panic ("STupleNamed: fieldNames and schema length mismatch" )
1562- }
15631561
15641562 return TupleSchemeNamed {FieldNames : fieldNames , Schema : schema , Nullable : true }
15651563}
15661564
15671565// Strict named tuple: exact field count
15681566func STupleNamedVal (fieldNames []string , schema ... Scheme ) TupleSchemeNamed {
1569- if len (fieldNames ) != len (schema ) {
1570- panic ("STupleNamedVal: fieldNames and schema length mismatch" )
1571- }
15721567 return TupleSchemeNamed {
15731568 FieldNames : fieldNames ,
15741569 Schema : schema ,
@@ -1580,9 +1575,6 @@ func STupleNamedVal(fieldNames []string, schema ...Scheme) TupleSchemeNamed {
15801575
15811576// Flexible named tuple: allows repeats/extra fields
15821577func STupleNamedValFlattened (fieldNames []string , schema ... Scheme ) TupleSchemeNamed {
1583- if len (fieldNames ) != len (schema ) {
1584- panic ("STupleNamedValFlattened: fieldNames and schema length mismatch" )
1585- }
15861578 return TupleSchemeNamed {
15871579 FieldNames : fieldNames ,
15881580 Schema : schema ,
@@ -1597,6 +1589,9 @@ func (s TupleSchemeNamed) IsNullable() bool {
15971589}
15981590
15991591func (s TupleSchemeNamed ) Validate (seq * access.SeqGetAccess ) error {
1592+ if len (s .FieldNames ) != len (s .Schema ) {
1593+ return NewSchemeError (ErrConstraintViolated , TupleSchemeNamedName , "" , 0 , SizeExact {Actual : len (s .FieldNames ), Exact : len (s .Schema )})
1594+ }
16001595 pos := seq .CurrentIndex ()
16011596 _ , err := precheck (TupleSchemeNamedName , pos , seq , types .TypeTuple , - 1 , s .IsNullable ())
16021597 if err != nil {
@@ -1624,6 +1619,9 @@ func (s TupleSchemeNamed) Validate(seq *access.SeqGetAccess) error {
16241619}
16251620
16261621func (s TupleSchemeNamed ) Decode (seq * access.SeqGetAccess ) (any , error ) {
1622+ if len (s .FieldNames ) != len (s .Schema ) {
1623+ return nil , NewSchemeError (ErrConstraintViolated , TupleSchemeNamedName , "" , 0 , SizeExact {Actual : len (s .FieldNames ), Exact : len (s .Schema )})
1624+ }
16271625 pos := seq .CurrentIndex ()
16281626 _ , err := precheck (TupleSchemeNamedName , pos , seq , types .TypeTuple , - 1 , s .IsNullable ())
16291627 if err != nil {
@@ -1665,13 +1663,15 @@ func (s TupleSchemeNamed) Decode(seq *access.SeqGetAccess) (any, error) {
16651663}
16661664
16671665func (s TupleSchemeNamed ) Encode (put * access.PutAccess , val any ) error {
1668-
1666+ if len (s .FieldNames ) != len (s .Schema ) {
1667+ return NewSchemeError (ErrConstraintViolated , TupleSchemeNamedName , "" , 0 , SizeExact {Actual : len (s .FieldNames ), Exact : len (s .Schema )})
1668+ }
16691669 if mapKV , ok := val .(map [string ]any ); ok {
16701670
16711671 nested := put .BeginTuple ()
16721672 defer put .EndNested (nested )
16731673 for i , key := range s .FieldNames {
1674- if sch , ok := s .Schema [i ].(SRepeatScheme ); ok {
1674+ if sch , ok := s .Schema [i ].(SRepeatScheme ); ok && s . Flatten {
16751675
16761676 minx := sch .min
16771677 max := sch .max
@@ -1846,3 +1846,115 @@ outer:
18461846 }
18471847 return nil
18481848}
1849+
1850+ // SchemeMultiCheckNamesScheme is a convenience scheme: every field is a SchemeBool.
1851+ type SchemeMultiCheckNamesScheme struct {
1852+ FieldNames []string
1853+ Nullable bool
1854+ }
1855+
1856+ func SMultiCheckNames (fieldNames []string ) SchemeMultiCheckNamesScheme {
1857+ return SchemeMultiCheckNamesScheme {
1858+ FieldNames : fieldNames ,
1859+ Nullable : true ,
1860+ }
1861+ }
1862+
1863+ func (s SchemeMultiCheckNamesScheme ) IsNullable () bool {
1864+ return s .Nullable
1865+ }
1866+
1867+ func (s SchemeMultiCheckNamesScheme ) Validate (seq * access.SeqGetAccess ) error {
1868+ pos := seq .CurrentIndex ()
1869+ _ , err := precheck (SchemeMultiCheckNamesSchemeNamed , pos , seq , types .TypeTuple , - 1 , s .IsNullable ())
1870+ if err != nil {
1871+ return err
1872+ }
1873+ sub , err := seq .PeekNestedSeq ()
1874+ if err != nil {
1875+ return NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1876+ }
1877+ if sub .ArgCount () != len (s .FieldNames ) {
1878+ return NewSchemeError (ErrConstraintViolated , SchemeMultiCheckNamesSchemeNamed , "" , pos ,
1879+ SizeExact {Actual : sub .ArgCount (), Exact : len (s .FieldNames )})
1880+ }
1881+ for range s .FieldNames {
1882+ err := SchemeBool {}.Validate (sub )
1883+ if err != nil {
1884+ return NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1885+ }
1886+ }
1887+ if err := seq .Advance (); err != nil {
1888+ return NewSchemeError (ErrUnexpectedEOF , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1889+ }
1890+ return nil
1891+ }
1892+
1893+ func (s SchemeMultiCheckNamesScheme ) Decode (seq * access.SeqGetAccess ) (any , error ) {
1894+ pos := seq .CurrentIndex ()
1895+ _ , err := precheck (SchemeMultiCheckNamesSchemeNamed , pos , seq , types .TypeTuple , - 1 , s .IsNullable ())
1896+ if err != nil {
1897+ return nil , err
1898+ }
1899+
1900+ selected := make ([]string , 0 )
1901+
1902+ sub , err := seq .PeekNestedSeq ()
1903+ if err != nil {
1904+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1905+ }
1906+ if sub .ArgCount () != len (s .FieldNames ) {
1907+ return nil , NewSchemeError (ErrConstraintViolated , SchemeMultiCheckNamesSchemeNamed , "" , pos ,
1908+ SizeExact {Actual : sub .ArgCount (), Exact : len (s .FieldNames )})
1909+ }
1910+
1911+ for _ , name := range s .FieldNames {
1912+ v , err := SchemeBool {}.Decode (sub )
1913+ if err != nil {
1914+ return nil , NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , name , pos , err )
1915+ }
1916+ if b , ok := v .(bool ); ok && b {
1917+ selected = append (selected , name )
1918+ }
1919+ }
1920+
1921+ if err := seq .Advance (); err != nil {
1922+ return nil , NewSchemeError (ErrUnexpectedEOF , SchemeMultiCheckNamesSchemeNamed , "" , pos , err )
1923+ }
1924+
1925+ // Return only the slice of selected names
1926+ return selected , nil
1927+ }
1928+
1929+ func (s SchemeMultiCheckNamesScheme ) Encode (put * access.PutAccess , val any ) error {
1930+
1931+ set := make (map [string ]struct {}, len (s .FieldNames ))
1932+ switch v := val .(type ) {
1933+ case []string :
1934+ for _ , name := range v {
1935+ set [name ] = struct {}{}
1936+ }
1937+ case []interface {}:
1938+ for _ , elem := range v {
1939+ str , ok := elem .(string )
1940+ if ! ok {
1941+ return NewSchemeError (ErrEncode , SchemeMultiCheckNamesSchemeNamed , "" , - 1 , ErrTypeMisMatch )
1942+ }
1943+ set [str ] = struct {}{}
1944+ }
1945+ default :
1946+ return NewSchemeError (ErrEncode , SchemeMultiCheckNamesSchemeNamed , "" , - 1 , ErrTypeMisMatch )
1947+ }
1948+
1949+ nested := put .BeginTuple ()
1950+ defer put .EndNested (nested )
1951+
1952+ for _ , key := range s .FieldNames {
1953+ _ , checked := set [key ]
1954+ err := SchemeBool {}.Encode (nested , checked )
1955+ if err != nil {
1956+ return NewSchemeError (ErrInvalidFormat , SchemeMultiCheckNamesSchemeNamed , key , - 1 , err )
1957+ }
1958+ }
1959+ return nil
1960+ }
0 commit comments