diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index d97953f..65aa1f6 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -3,9 +3,9 @@ name: Go on: push: - branches: [ "main" ] + branches: [ "main", "dev" ] pull_request: - branches: [ "main" ] + branches: [ "main", "dev" ] jobs: diff --git a/README.md b/README.md index be8d666..cc8c1f8 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This module is split into four main packages: - **[idv](idv/README.md)** - the benc ID validation, raw serialization with ID prefixing ### [Security](SECURITY.md) + ### [Benchmarks](https://github.com/alecthomas/go_serialization_benchmarks) ### benc.go @@ -23,4 +24,4 @@ This module is split into four main packages: ## License -[MIT](https://choosealicense.com/licenses/mit/) +[MIT](LICENSE) diff --git a/cmd/bencgen/README.md b/cmd/bencgen/README.md index 1339b7a..d6e9a0c 100644 --- a/cmd/bencgen/README.md +++ b/cmd/bencgen/README.md @@ -1,8 +1,9 @@ # bencgen -The code generator for benc, handling both forward and backward compatibility. +A code generator for Benc, ensuring both forward and backward compatibility. + +## Table of Contents -## Table Of Contents - [Requirements](#requirements) - [Installation](#installation) - [Usage](#usage) @@ -11,18 +12,21 @@ The code generator for benc, handling both forward and backward compatibility. - [Breaking Changes Detector](#breaking-changes-detector-bcd) - [Maintaining](#maintaining) - [Examples and Tests](#examples-and-tests) -- [Schema Grammar](#header) +- [Enums](#enums) +- [Schema Grammar](#schema-grammar) - [Languages](#languages) - [License](#license) ## Requirements -- Go for installing and executing `bencgen`. -- [benc standard](../../std/README.md) -- [bencgen impl](../../impl/gen/README.md) + +- Go (for installing and running `bencgen`) +- [Benc Standard](../../std/README.md) +- [Bencgen Implementation](../../impl/gen/README.md) ## Installation -1. Install `bencgen`: +1. Install `bencgen` using the following command: + ```bash go install github.com/deneonet/benc/cmd/bencgen ``` @@ -31,46 +35,51 @@ go install github.com/deneonet/benc/cmd/bencgen Arguments: -- `--in`: The .benc input file (required) +- `--in`: The input `.benc` file (required) - `--out`: The output directory (optional) -- `--lang`: The [language](#languages) to compile into (required) -- `--file`: The output file name (optional) -- `--force`: Disables the breaking changes detector (optional, not recommended, when the schema is already in-use in e.g. a software) +- `--lang`: The target [language](#languages) to compile into (required) +- `--file`: The name of the output file (optional) +- `--force`: Disable the breaking changes detector (optional, not recommended if the schema is in use, e.g., in software) ## Generating Example -1. Create a .benc file (e.g. `person.benc`). +1. Create a `.benc` file (e.g., `person.benc`). 2. Write a schema, for example: - ```plaintext - header person; + ```plaintext + header person; + + ctr Person { + byte age = 1; + string name = 2; + Parents parents = 3; + Child child = 4; + } - ctr Person { - byte age = 1; - string name = 2; - Parents parents = 3; - Child child = 4; - } + ctr Child { + byte age = 1; + string name = 2; + Parents parents = 3; + } - ctr Child { - byte age = 1; - string name = 2; - Parents parents = 3; - } + ctr Parents { + string mother = 1; + string father = 2; + } + ``` - ctr Parents { - string mother = 1; - string father = 2; - } - ``` +3. Generate Go code with the following command: -3. Generate Go code using `bencgen --in person.benc --lang go`. -4. Find instructions for using the generated code in your selected language: - - [Go](#go-usage-example) +```bash +bencgen --in person.benc --lang go +``` + +4. Follow the instructions for using the generated code in the selected language: + - [Go Usage Example](#go-usage-example) ## Go Usage Example -After generating, a file called `out/person.benc.go` will be created. To marshal and unmarshal the person: +After generating, a file called `out/person.benc.go` will be created. To marshal and unmarshal the `Person` data: ```go package main @@ -111,28 +120,31 @@ func main() { ## Breaking Changes Detector (BCD) BCD detects breaking changes, such as: + - A field exists but is marked as reserved. - A field was removed but is not marked as reserved. -- The type of a field changed, but its ID stayed the same. +- The type of a field changed, but its ID remained the same. ## Maintaining -To maintain your benc schema, follow these rules: -- Mark a field as reserved when removed. -- New fields must be appended at the bottom (fields must be ordered by their IDs in ascending order). -- If the type of a field changes, it requires a new ID, and the old ID must be marked as reserved. -- Use [BCD](#breaking-changes-detector-bcd) (on by default); it catches and reports compatibility issues. +To maintain your Benc schema, follow these rules: + +- Mark removed fields as reserved. +- New fields must be appended at the bottom (fields should be ordered by their IDs in ascending order). +- If the type of a field changes, assign it a new ID and mark the old ID as reserved. +- Use [BCD](#breaking-changes-detector-bcd) (enabled by default) to catch and report compatibility issues. ### Reserving IDs -Using the `person` schema from [earlier](#generating-example), if we remove the `parents` field, which had `3`as ID, then ID `3` must be marked as reserved: +For example, using the `person` schema from the [earlier section](#generating-example), if the `parents` field is removed (ID `3`), mark ID `3` as reserved: `person.benc`: + ```plaintext header person; ctr Person { - reserved 3; # reserved the parents field ID + reserved 3; # Reserved the 'parents' field ID byte age = 1; string name = 2; @@ -154,63 +166,134 @@ ctr Parents { ## Examples and Tests See all tests [here](../../testing). -See tests specifically about forward and backward compatibility [here](../../testing/person/main_person_test.go). +For tests specifically related to forward and backward compatibility, see [here](../../testing/person/main_person_test.go). + +## Enums + +Enums example: + +```plaintext +header person; + +enum JobStatus { + Employed, + Unemployed +} + +ctr Person { + byte age = 1; + string name = 2; + JobStatus jobStatus = 3; +} +``` + +Enums are treated as named integers. Forward and backward compatibility is preserved even when fields are added or removed from an enum, as the benc protocol doesn't rely on them. -## Header +## Schema Grammar + +A schema consists of the following components: + +### Header A header consists of: `header` IDENTIFIER `;` -| **Benc** | **Golang** | -|:--------:|:----------:| +| **Benc** | **Go** | +| :----------: | :-----------: | | `header ...` | `package ...` | -## Fields +### Fields + +A field consists of: "[ATTR](#type-attributes) [TYPE](#types) IDENTIFIER = ID ;" || "[CONTAINER_OR_ENUM_NAME](#containers-or-enums) IDENTIFIER = ID ;" + +- The ID must be no larger than `65535`. +- A field of type `string` may have [type attributes](#type-attributes). -A field consists of: [TYPE](#types) IDENTIFIER `=` ID `;` +Example of a simple field: -- The ID may not be larger than `65535`. -- A field with type `string` may have [type attributes](#type-attributes). +```plaintext +string name = 1; +``` -### Examples +Example of a field with type attributes: -Field: -`string name = 1;` -Type Attributes: -`@unsafe string name = 1;` +```plaintext +@unsafe string name = 1; +``` -**!!** Type Attributes **must** be placed before the type, e.g. for an array: -`[] @unsafe string names = 1;` +**Note:** Type attributes **must** precede the type, e.g., for arrays: + +```plaintext +[] @unsafe string names = 1; +``` #### Type Attributes -- **unsafe** (only in Go): Uses the `unsafe` package, allowing faster unmarshal operations. -Multiple `unsafe` type attributes are ignored. + +- **unsafe** (Go only): Uses the `unsafe` package, allowing faster unmarshalling operations. Multiple `unsafe` attributes are ignored. ## Types -| **Benc** | **Golang** | -|:--------:|:----------:| -| `byte` | `byte` | -| `bytes` | `[]byte` | -| `int` | `int` | -| `int16` | `int16` | -| `int32` | `int32` | -| `int64` | `int64` | -| `uint` | `uint` | -| `uint16` | `uint16` | -| `uint32` | `uint32` | -| `uint64` | `uint64` | +| **Benc** | **Go** | +| :-------: | :-------: | +| `byte` | `byte` | +| `bytes` | `[]byte` | +| `int` | `int` | +| `int16` | `int16` | +| `int32` | `int32` | +| `int64` | `int64` | +| `uint` | `uint` | +| `uint16` | `uint16` | +| `uint32` | `uint32` | +| `uint64` | `uint64` | | `float32` | `float32` | | `float64` | `float64` | -| `bool` | `bool` | -| `string` | `string` | -| `[]T` | `[]T` | -| `` | `map[K]V` | +| `bool` | `bool` | +| `string` | `string` | +| `[]T` | `[]T` | +| `` | `map[K]V` | + +### Containers Or Enums + +A container or enum name refers to another defined structure. + +**Container**: + +``` +ctr Person { + byte age = 1; + string name = 2; + Child child = 4; +} +``` -The name of another container is also a type (`Container`). +Reference: + +``` +ctr Person2 { + Person person = 1; +} +``` + +**Enum**: + +``` +enum JobStatus { + Employed, + Unemployed +} +``` + +Reference: + +``` +ctr Person { + JobStatus jobStatus = 1; +} +``` ## Languages Valid values for `--lang` are: + - `go` ## License diff --git a/cmd/bencgen/codegens/entry-gen.go b/cmd/bencgen/codegens/entry-gen.go index 36bb46c..51655b3 100644 --- a/cmd/bencgen/codegens/entry-gen.go +++ b/cmd/bencgen/codegens/entry-gen.go @@ -9,123 +9,173 @@ import ( "github.com/deneonet/benc/cmd/bencgen/utils" ) -type GeneratorLanguage string +type GenLang string const ( - GenGolang GeneratorLanguage = "go" + GoGenLang GenLang = "go" ) -func (lang GeneratorLanguage) String() string { +func (lang GenLang) String() string { switch lang { - case GenGolang: - return "golang" + case GoGenLang: + return "go" default: return "invalid" } } -type Generator interface { +type Gen interface { File() string - Lang() GeneratorLanguage - GenHeader(stmt *parser.HeaderStmt) string - GenStruct(ctrDeclarations []string, stmt *parser.CtrStmt) string - GenReservedIds(stmt *parser.CtrStmt) string - GenSize(stmt *parser.CtrStmt) string - GenMarshal(stmt *parser.CtrStmt) string - GenUnmarshal(stmt *parser.CtrStmt) string - GenSizePlain(stmt *parser.CtrStmt) string - GenMarshalPlain(stmt *parser.CtrStmt) string - GenUnmarshalPlain(stmt *parser.CtrStmt) string + Lang() GenLang + + GenHeader() string + GenEnum() string + GenStruct() string + GenReservedIds() string + GenSize() string + GenMarshal() string + GenUnmarshal() string + GenSizePlain() string + GenMarshalPlain() string + GenUnmarshalPlain() string + + HasHeader() bool + + SetCtrDecls(ctrDecls []string) + SetEnumDecls(ctrDecls []string) + + SetCtrStatement(stmt *parser.CtrStmt) + SetEnumStatement(stmt *parser.EnumStmt) + SetHeaderStatement(stmt *parser.HeaderStmt) } -func NewGenerator(lang GeneratorLanguage, file string) Generator { +func NewGen(lang GenLang, file string) Gen { switch lang { - case GenGolang: - return NewGoGenerator(file) + case GoGenLang: + return NewGoGen(file) default: return nil } } -func logErrorAndExit(g Generator, msg string) { +func logErrorAndExit(g Gen, msg string) { fmt.Printf("\n\033[1;31m[bencgen] Error:\033[0m\n"+ " \033[1;37mFile:\033[0m %s\n"+ " \033[1;37mMessage:\033[0m %s\n", g.File(), msg) os.Exit(1) } -var unallowedNames = []string{"b", "n", "id", "r"} +var disallowedNames = []string{"b", "n", "id", "r"} -func Generate(gen Generator, nodes []parser.Node) string { - containsHeader := false - ctrDeclarations := []string{} +func Generate(g Gen, nodes []parser.Node) string { + ctrDecls := []string{} + enumDecls := []string{} + + res := fmt.Sprintf("// Code generated by bencgen %s. DO NOT EDIT.\n// source: %s\n\n", + g.Lang().String(), g.File()) - res := fmt.Sprintf("// Code generated by bencgen %s. DO NOT EDIT.\n// source: %s\n\n", gen.Lang().String(), gen.File()) for _, node := range nodes { switch stmt := node.(type) { case *parser.CtrStmt: - validateCtrStmt(gen, stmt, ctrDeclarations) - ctrDeclarations = append(ctrDeclarations, stmt.Name) + validateCtrStmt(g, stmt, enumDecls, ctrDecls) + ctrDecls = append(ctrDecls, stmt.Name) + case *parser.EnumStmt: + validateEnumStmt(g, stmt, enumDecls, ctrDecls) + enumDecls = append(enumDecls, stmt.Name) } } + g.SetCtrDecls(ctrDecls) + g.SetEnumDecls(enumDecls) + for _, node := range nodes { switch stmt := node.(type) { case *parser.HeaderStmt: - if containsHeader { - logErrorAndExit(gen, "Multiple `header` declarations.") + if g.HasHeader() { + logErrorAndExit(g, "Multiple 'header' declarations.") } - res += gen.GenHeader(stmt) - containsHeader = true + + g.SetHeaderStatement(stmt) + res += g.GenHeader() case *parser.CtrStmt: - if !containsHeader { - logErrorAndExit(gen, "A `header` was not declared.") + if !g.HasHeader() { + logErrorAndExit(g, "A 'header' was not declared.") } - validateContainerFields(gen, stmt, ctrDeclarations) - res += generateContainerCode(gen, stmt, ctrDeclarations) + validateContainerFields(g, stmt, ctrDecls, enumDecls) + + g.SetCtrStatement(stmt) + res += generateCtr(g) + case *parser.EnumStmt: + if !g.HasHeader() { + logErrorAndExit(g, "A 'header' was not declared.") + } + validateEnumFields(g, stmt) + + g.SetEnumStatement(stmt) + res += g.GenEnum() } } return res } -func validateCtrStmt(gen Generator, stmt *parser.CtrStmt, ctrDeclarations []string) { - if slices.Contains(ctrDeclarations, stmt.Name) { - logErrorAndExit(gen, fmt.Sprintf("Multiple containers with the same name \"%s\".", stmt.Name)) +func validateCtrStmt(g Gen, stmt *parser.CtrStmt, enumDecls []string, ctrDecls []string) { + if slices.Contains(enumDecls, stmt.Name) { + logErrorAndExit(g, fmt.Sprintf("A enum with the same name \"%s\" is already declared.", stmt.Name)) + } + + if slices.Contains(ctrDecls, stmt.Name) { + logErrorAndExit(g, fmt.Sprintf("Multiple containers with the same name \"%s\".", stmt.Name)) + } + + if len(stmt.Fields) == 0 { + logErrorAndExit(g, fmt.Sprintf("Empty container \"%s\".", stmt.Name)) + } +} + +func validateEnumStmt(g Gen, stmt *parser.EnumStmt, enumDecls []string, ctrDecls []string) { + if slices.Contains(enumDecls, stmt.Name) { + logErrorAndExit(g, fmt.Sprintf("Multiple enums with the same name \"%s\".", stmt.Name)) + } + + if slices.Contains(ctrDecls, stmt.Name) { + logErrorAndExit(g, fmt.Sprintf("A container with the same name \"%s\" is already declared.", stmt.Name)) } + if len(stmt.Fields) == 0 { - logErrorAndExit(gen, fmt.Sprintf("Empty container \"%s\".", stmt.Name)) + logErrorAndExit(g, fmt.Sprintf("Empty enum \"%s\".", stmt.Name)) } } -func validateContainerFields(gen Generator, stmt *parser.CtrStmt, ctrDeclarations []string) { +func validateContainerFields(g Gen, stmt *parser.CtrStmt, ctrDecls []string, enumDecls []string) { var ids []uint16 var lastID uint16 var fieldNames []string for _, field := range stmt.Fields { - if ctr, found := utils.FindUndeclaredContainers(ctrDeclarations, field.Type); found { - logErrorAndExit(gen, fmt.Sprintf("Container \"%s\" not declared on \"%s\" (\"%s\").", ctr, stmt.Name, field.Name)) + _, enumNotFound := utils.FindUndeclaredContainersOrEnums(enumDecls, field.Type) + if ctrEnum, notFound := utils.FindUndeclaredContainersOrEnums(ctrDecls, field.Type); notFound && enumNotFound { + logErrorAndExit(g, fmt.Sprintf("Container/Enum \"%s\" not declared on \"%s\" (\"%s\").", ctrEnum, stmt.Name, field.Name)) } if field.Id == 0 { - logErrorAndExit(gen, fmt.Sprintf("Field \"%s\" has an ID of \"0\" on \"%s\".", field.Name, stmt.Name)) + logErrorAndExit(g, fmt.Sprintf("Field \"%s\" has an ID of \"0\" on \"%s\".", field.Name, stmt.Name)) } if slices.Contains(ids, field.Id) { - logErrorAndExit(gen, fmt.Sprintf("Multiple fields with the same ID \"%d\" on \"%s\".", field.Id, stmt.Name)) + logErrorAndExit(g, fmt.Sprintf("Multiple fields with the same ID \"%d\" on \"%s\".", field.Id, stmt.Name)) } if lastID > field.Id { - logErrorAndExit(gen, fmt.Sprintf("Fields must be ordered by their IDs in ascending order on \"%s\".", stmt.Name)) + logErrorAndExit(g, fmt.Sprintf("Fields must be ordered by their IDs in ascending order on \"%s\".", stmt.Name)) } if slices.Contains(fieldNames, field.Name) { - logErrorAndExit(gen, fmt.Sprintf("Multiple fields with the same name \"%s\" on \"%s\".", field.Name, stmt.Name)) + logErrorAndExit(g, fmt.Sprintf("Multiple fields with the same name \"%s\" on \"%s\".", field.Name, stmt.Name)) } - if slices.Contains(unallowedNames, utils.ToLower(stmt.Name)) { - logErrorAndExit(gen, fmt.Sprintf("Unallowed container name \"%s\".", stmt.Name)) + if slices.Contains(disallowedNames, utils.ToLower(stmt.Name)) { + logErrorAndExit(g, fmt.Sprintf("Unallowed container name \"%s\".", stmt.Name)) } lastID = field.Id @@ -134,13 +184,24 @@ func validateContainerFields(gen Generator, stmt *parser.CtrStmt, ctrDeclaration } } -func generateContainerCode(gen Generator, stmt *parser.CtrStmt, ctrDeclarations []string) string { - return gen.GenStruct(ctrDeclarations, stmt) + - gen.GenReservedIds(stmt) + - gen.GenSize(stmt) + - gen.GenSizePlain(stmt) + - gen.GenMarshal(stmt) + - gen.GenMarshalPlain(stmt) + - gen.GenUnmarshal(stmt) + - gen.GenUnmarshalPlain(stmt) +func validateEnumFields(g Gen, stmt *parser.EnumStmt) { + var fieldNames []string + + for _, field := range stmt.Fields { + if slices.Contains(fieldNames, field) { + logErrorAndExit(g, fmt.Sprintf("Multiple fields with the same name \"%s\" on \"%s\".", field, stmt.Name)) + } + fieldNames = append(fieldNames, field) + } +} + +func generateCtr(g Gen) string { + return g.GenStruct() + + g.GenReservedIds() + + g.GenSize() + + g.GenSizePlain() + + g.GenMarshal() + + g.GenMarshalPlain() + + g.GenUnmarshal() + + g.GenUnmarshalPlain() } diff --git a/cmd/bencgen/codegens/golang-gen.go b/cmd/bencgen/codegens/golang-gen.go index 3e4bd7c..de0f8bc 100644 --- a/cmd/bencgen/codegens/golang-gen.go +++ b/cmd/bencgen/codegens/golang-gen.go @@ -2,6 +2,7 @@ package codegens import ( "fmt" + "slices" "strings" "github.com/deneonet/benc/cmd/bencgen/lexer" @@ -9,115 +10,134 @@ import ( "github.com/deneonet/benc/cmd/bencgen/utils" ) -type GoGenerator struct { +type GoCtrStmt struct { + PublicName string + PrivateName string + + DefaultName string + + Fields []parser.Field + ReservedIds []uint16 +} + +type GoEnumStmt struct { + PublicName string + PrivateName string + + DefaultName string + + Fields []string +} + +type GoField struct { + Id uint16 + + PublicName string + PrivateName string + DefaultName string + + Type *parser.Type +} + +func (f *GoField) AppendUnsafeIfPresent() string { + return f.Type.AppendUnsafeIfPresent() +} + +type GoGen struct { file string + + ctrDecls []string + enumDecls []string + + plainGen bool + headerStmt *parser.HeaderStmt + + // currently generated... + + field GoField + ctrStmt GoCtrStmt + enumStmt GoEnumStmt } -func NewGoGenerator(file string) *GoGenerator { - return &GoGenerator{file: file} +func NewGoGen(file string) *GoGen { + return &GoGen{file: file} } -func (gg GoGenerator) File() string { - return gg.file +func (g *GoGen) File() string { + return g.file } -func (gg GoGenerator) Lang() GeneratorLanguage { - return GenGolang +func (*GoGen) Lang() GenLang { + return GoGenLang } -func getSizeFunc(name string, field parser.Field, plain bool) string { - fieldName := utils.ToUpper(field.Name) - fieldType := field.Type - switch { - case field.Type.IsArray: - return fmt.Sprintf("bstd.SizeSlice(%s.%s, %s)", name, fieldName, getElemSizeFunc(fieldType.ChildType)) - case field.Type.IsMap: - return fmt.Sprintf("bstd.SizeMap(%s.%s, %s, %s)", name, fieldName, getElemSizeFunc(fieldType.MapKeyType), getElemSizeFunc(fieldType.ChildType)) - case field.Type.CtrName != "": - if plain { - return fmt.Sprintf("%s.%s.SizePlain()", name, fieldName) - } - return fmt.Sprintf("%s.%s.size(%d)", name, fieldName, field.Id) - default: - switch fieldType.TokenType { - case lexer.STRING, lexer.BYTES, lexer.INT, lexer.UINT: - return fmt.Sprintf("bstd.Size%s(%s.%s)", fieldType.TokenType.String(), name, fieldName) - } - return fmt.Sprintf("bstd.Size%s()", fieldType.TokenType.String()) - } +func (g *GoGen) IsCtr(extStructureName string) bool { + return slices.Contains(g.ctrDecls, extStructureName) } -func getElemSizeFunc(t *parser.Type) string { - switch { - case t.IsArray: - return fmt.Sprintf("func (s %s) int { return bstd.SizeSlice(s, %s) }", utils.BencTypeToGolang(t), getElemSizeFunc(t.ChildType)) - case t.IsMap: - return fmt.Sprintf("func (s %s) int { return bstd.SizeMap(s, %s, %s) }", utils.BencTypeToGolang(t), getElemSizeFunc(t.MapKeyType), getElemSizeFunc(t.ChildType)) - case t.CtrName != "": - return fmt.Sprintf("func (s %s) int { return s.SizePlain() }", utils.ToUpper(t.CtrName)) - default: - return "bstd.Size" + t.TokenType.String() - } +func (g *GoGen) IsEnum(extStructureName string) bool { + return slices.Contains(g.enumDecls, extStructureName) } -func getMarshalFunc(name string, field parser.Field, plain bool) string { - fieldName := utils.ToUpper(field.Name) - switch { - case field.Type.IsArray: - return fmt.Sprintf("bstd.MarshalSlice(n, b, %s.%s, %s)", name, fieldName, getElemMarshalFunc(field.Type.ChildType)) - case field.Type.IsMap: - return fmt.Sprintf("bstd.MarshalMap(n, b, %s.%s, %s, %s)", name, fieldName, getElemMarshalFunc(field.Type.MapKeyType), getElemMarshalFunc(field.Type.ChildType)) - case field.Type.CtrName != "": - if plain { - return fmt.Sprintf("%s.%s.MarshalPlain(n, b)", name, fieldName) +func (g *GoGen) ForEachCtrFields(f func(i int)) { + for i, field := range g.ctrStmt.Fields { + g.field = GoField{ + Id: field.Id, + + PublicName: utils.ToUpper(field.Name), + PrivateName: utils.ToLower(field.Name), + DefaultName: field.Name, + + Type: field.Type, } - return fmt.Sprintf("%s.%s.marshal(n, b, %d)", name, fieldName, field.Id) - default: - return fmt.Sprintf("bstd.Marshal%s%s(n, b, %s.%s)", field.GetUnsafeStr(), field.Type.TokenType.String(), name, fieldName) + f(i) } } -func getElemMarshalFunc(t *parser.Type) string { - switch { - case t.IsArray: - return fmt.Sprintf("func (n int, b []byte, s %s) int { return bstd.MarshalSlice(n, b, s, %s) }", utils.BencTypeToGolang(t), getElemMarshalFunc(t.ChildType)) - case t.IsMap: - return fmt.Sprintf("func (n int, b []byte, s %s) int { return bstd.MarshalMap(n, b, s, %s, %s) }", utils.BencTypeToGolang(t), getElemMarshalFunc(t.MapKeyType), getElemMarshalFunc(t.ChildType)) - case t.CtrName != "": - return fmt.Sprintf("func (n int, b []byte, s %s) int { return s.MarshalPlain(n, b) }", utils.ToUpper(t.CtrName)) - default: - return "bstd.Marshal" + t.GetUnsafeStr() + t.TokenType.String() +func (g *GoGen) ForEachEnumFields(f func(i int, field string)) { + for i, field := range g.enumStmt.Fields { + f(i, utils.ToUpper(field)) } } -func getUnmarshalFunc(name string, field parser.Field, plain bool) string { - fieldName := utils.ToUpper(field.Name) - switch { - case field.Type.IsArray: - return fmt.Sprintf("bstd.UnmarshalSlice[%s](n, b, %s)", utils.BencTypeToGolang(field.Type.ChildType), getElemUnmarshalFunc(field.Type.ChildType)) - case field.Type.IsMap: - return fmt.Sprintf("bstd.UnmarshalMap[%s, %s](n, b, %s, %s)", utils.BencTypeToGolang(field.Type.MapKeyType), utils.BencTypeToGolang(field.Type.ChildType), getElemUnmarshalFunc(field.Type.MapKeyType), getElemUnmarshalFunc(field.Type.ChildType)) - case field.Type.CtrName != "" && plain: - return fmt.Sprintf("%s.%s.UnmarshalPlain(n, b)", name, fieldName) - default: - return fmt.Sprintf("bstd.Unmarshal%s%s(n, b)", field.GetUnsafeStr(), field.Type.TokenType.String()) +func (g *GoGen) HasHeader() bool { + return g.headerStmt != nil +} + +func (g *GoGen) SetCtrStatement(stmt *parser.CtrStmt) { + g.ctrStmt = GoCtrStmt{ + PublicName: utils.ToUpper(stmt.Name), + PrivateName: utils.ToLower(stmt.Name), + + DefaultName: stmt.Name, + Fields: stmt.Fields, + ReservedIds: stmt.ReservedIds, } } -func getElemUnmarshalFunc(t *parser.Type) string { - switch { - case t.IsArray: - return fmt.Sprintf("func (n int, b []byte) (int, %s, error) { return bstd.UnmarshalSlice[%s](n, b, %s) }", utils.BencTypeToGolang(t), utils.BencTypeToGolang(t.ChildType), getElemUnmarshalFunc(t.ChildType)) - case t.IsMap: - return fmt.Sprintf("func (n int, b []byte) (int, %s, error) { return bstd.UnmarshalMap[%s, %s](n, b, %s, %s) }", utils.BencTypeToGolang(t), utils.BencTypeToGolang(t.MapKeyType), utils.BencTypeToGolang(t.ChildType), getElemUnmarshalFunc(t.MapKeyType), getElemUnmarshalFunc(t.ChildType)) - case t.CtrName != "": - return fmt.Sprintf("func (n int, b []byte, s *%s) (int, error) { return s.UnmarshalPlain(n, b) }", utils.ToUpper(t.CtrName)) - default: - return "bstd.Unmarshal" + t.GetUnsafeStr() + t.TokenType.String() +func (g *GoGen) SetEnumStatement(stmt *parser.EnumStmt) { + g.enumStmt = GoEnumStmt{ + PublicName: utils.ToUpper(stmt.Name), + PrivateName: utils.ToLower(stmt.Name), + + DefaultName: stmt.Name, + Fields: stmt.Fields, } } -func (gen GoGenerator) GenHeader(stmt *parser.HeaderStmt) string { +func (g *GoGen) SetHeaderStatement(stmt *parser.HeaderStmt) { + g.headerStmt = stmt +} + +func (g *GoGen) SetCtrDecls(ctrDecls []string) { + g.ctrDecls = ctrDecls +} + +func (g *GoGen) SetEnumDecls(enumDecls []string) { + g.enumDecls = enumDecls +} + +func (g *GoGen) GenHeader() string { return fmt.Sprintf( `package %s @@ -126,12 +146,7 @@ import ( "github.com/deneonet/benc/impl/gen" ) -`, stmt.Name) -} - -func (gen GoGenerator) GenReservedIds(stmt *parser.CtrStmt) string { - return fmt.Sprintf("// Reserved Ids - %s\nvar %sRIds = []uint16{%s}\n\n", - stmt.Name, utils.ToLower(stmt.Name), joinUint16(stmt.ReservedIds)) +`, g.headerStmt.Name) } func joinUint16(ids []uint16) string { @@ -145,76 +160,246 @@ func joinUint16(ids []uint16) string { return sb.String() } -func (gen GoGenerator) GenStruct(ctrDeclarations []string, stmt *parser.CtrStmt) string { +func (g *GoGen) GenReservedIds() string { + ctr := g.ctrStmt + return fmt.Sprintf("// Reserved Ids - %s\nvar %sRIds = []uint16{%s}\n\n", + ctr.DefaultName, ctr.PrivateName, joinUint16(ctr.ReservedIds)) +} + +func (g *GoGen) GenStruct() string { var sb strings.Builder - stmtName := utils.ToUpper(stmt.Name) - sb.WriteString(fmt.Sprintf("// Struct - %s\ntype %s struct {\n", stmtName, stmtName)) - for _, field := range stmt.Fields { - sb.WriteString(fmt.Sprintf(" %s %s\n", utils.ToUpper(field.Name), utils.BencTypeToGolang(field.Type))) - } + ctr := g.ctrStmt + + sb.WriteString(fmt.Sprintf("// Struct - %s\ntype %s struct {\n", + ctr.DefaultName, ctr.PublicName)) + + g.ForEachCtrFields(func(i int) { + field := g.field + sb.WriteString(fmt.Sprintf(" %s %s\n", + field.PublicName, utils.BencTypeToGolang(field.Type))) + }) + sb.WriteString("}\n\n") return sb.String() } -func (gen GoGenerator) GenSize(stmt *parser.CtrStmt) string { - privStmtName := utils.ToLower(stmt.Name) - publStmtName := utils.ToUpper(stmt.Name) +func (g *GoGen) GenEnum() string { + var sb strings.Builder + enum := g.enumStmt + + sb.WriteString(fmt.Sprintf("// Enum - %s\ntype %s int\nconst (\n", + enum.DefaultName, enum.PublicName)) + + g.ForEachEnumFields(func(i int, field string) { + if i == 0 { + sb.WriteString(fmt.Sprintf(" %s%s %s = iota\n", + enum.PublicName, field, enum.PublicName)) + return + } + sb.WriteString(fmt.Sprintf(" %s%s\n", + enum.PublicName, field)) + }) + + sb.WriteString(")\n\n") + return sb.String() +} + +func (g *GoGen) getSizeFunc() string { + ctr := g.ctrStmt + field := g.field + + switch { + case field.Type.IsArray: + return fmt.Sprintf("bstd.SizeSlice(%s.%s, %s)", + ctr.PrivateName, field.PublicName, g.getElemSizeFunc(field.Type.ChildType)) + case field.Type.IsMap: + return fmt.Sprintf("bstd.SizeMap(%s.%s, %s, %s)", + ctr.PrivateName, field.PublicName, g.getElemSizeFunc(field.Type.MapKeyType), g.getElemSizeFunc(field.Type.ChildType)) + case field.Type.ExtStructure != "": + if g.IsEnum(field.Type.ExtStructure) { + return fmt.Sprintf("bgenimpl.SizeEnum(%s.%s)", + ctr.PrivateName, field.PublicName) + } + + if g.plainGen { + return fmt.Sprintf("%s.%s.SizePlain()", + ctr.PrivateName, field.PublicName) + } + return fmt.Sprintf("%s.%s.size(%d)", + ctr.PrivateName, field.PublicName, field.Id) + default: + switch field.Type.TokenType { + case lexer.STRING, lexer.BYTES, lexer.INT, lexer.UINT: + return fmt.Sprintf("bstd.Size%s(%s.%s)", + field.Type.TokenType.String(), ctr.PrivateName, field.PublicName) + } + + return fmt.Sprintf("bstd.Size%s()", + field.Type.TokenType.String()) + } +} + +func (g *GoGen) getElemSizeFunc(t *parser.Type) string { + switch { + case t.IsArray: + return fmt.Sprintf("func (s %s) int { return bstd.SizeSlice(s, %s) }", + utils.BencTypeToGolang(t), g.getElemSizeFunc(t.ChildType)) + case t.IsMap: + return fmt.Sprintf("func (s %s) int { return bstd.SizeMap(s, %s, %s) }", + utils.BencTypeToGolang(t), g.getElemSizeFunc(t.MapKeyType), g.getElemSizeFunc(t.ChildType)) + case t.ExtStructure != "": + if g.IsEnum(t.ExtStructure) { + return "bgenimpl.SizeEnum" + } + + return fmt.Sprintf("func (s %s) int { return s.SizePlain() }", + utils.ToUpper(t.ExtStructure)) + default: + return "bstd.Size" + t.TokenType.String() + } +} +func (g *GoGen) GenSize() string { var sb strings.Builder - sb.WriteString(fmt.Sprintf("// Size - %s\nfunc (%s *%s) Size() int {\n return %s.size(0)\n}\n\n", stmt.Name, privStmtName, publStmtName, privStmtName)) - sb.WriteString(fmt.Sprintf("// Nested Size - %s\nfunc (%s *%s) size(id uint16) (s int) {\n", stmt.Name, privStmtName, publStmtName)) + ctr := g.ctrStmt + + sb.WriteString(fmt.Sprintf("// Size - %s\nfunc (%s *%s) Size() int {\n return %s.size(0)\n}\n\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName, ctr.PrivateName)) + + sb.WriteString(fmt.Sprintf("// Nested Size - %s\nfunc (%s *%s) size(id uint16) (s int) {\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName)) + + g.ForEachCtrFields(func(_ int) { + field := g.field - for _, field := range stmt.Fields { tagSize := 2 - if field.Id > 255 { + if g.field.Id > 255 { tagSize = 3 } - sb.WriteString(fmt.Sprintf(" s += %s", getSizeFunc(privStmtName, field, false))) - if field.Type.CtrName == "" { + sb.WriteString(fmt.Sprintf(" s += %s", g.getSizeFunc())) + + if !g.IsCtr(field.Type.ExtStructure) { sb.WriteString(fmt.Sprintf(" + %d\n", tagSize)) } else { sb.WriteString("\n") } - } + }) sb.WriteString("\n if id > 255 {\n s += 5\n return\n }\n s += 4\n return\n}\n\n") return sb.String() } -func (gen GoGenerator) GenSizePlain(stmt *parser.CtrStmt) string { - privStmtName := utils.ToLower(stmt.Name) - publStmtName := utils.ToUpper(stmt.Name) - +func (g *GoGen) GenSizePlain() string { var sb strings.Builder - sb.WriteString(fmt.Sprintf("// SizePlain - %s\nfunc (%s *%s) SizePlain() (s int) {\n", stmt.Name, privStmtName, publStmtName)) - for _, field := range stmt.Fields { - sb.WriteString(fmt.Sprintf(" s += %s\n", getSizeFunc(privStmtName, field, true))) - } + ctr := g.ctrStmt + + g.plainGen = true + defer func() { g.plainGen = false }() + + sb.WriteString(fmt.Sprintf("// SizePlain - %s\nfunc (%s *%s) SizePlain() (s int) {\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName)) + + g.ForEachCtrFields(func(_ int) { + sb.WriteString(fmt.Sprintf(" s += %s\n", g.getSizeFunc())) + }) + sb.WriteString(" return\n}\n\n") return sb.String() } -func (gen GoGenerator) GenMarshal(stmt *parser.CtrStmt) string { - privStmtName := utils.ToLower(stmt.Name) - publStmtName := utils.ToUpper(stmt.Name) +func (g *GoGen) getMarshalFunc() string { + ctr := g.ctrStmt + field := g.field - var sb strings.Builder - sb.WriteString(fmt.Sprintf("// Marshal - %s\nfunc (%s *%s) Marshal(b []byte) {\n %s.marshal(0, b, 0)\n}\n\n", stmt.Name, privStmtName, publStmtName, privStmtName)) - sb.WriteString(fmt.Sprintf("// Nested Marshal - %s\nfunc (%s *%s) marshal(tn int, b []byte, id uint16) (n int) {\n n = bgenimpl.MarshalTag(tn, b, bgenimpl.Container, id)\n", stmt.Name, privStmtName, publStmtName)) + switch { + case field.Type.IsArray: + return fmt.Sprintf("bstd.MarshalSlice(n, b, %s.%s, %s)", + ctr.PrivateName, field.PublicName, g.getElemMarshalFunc(field.Type.ChildType)) + case field.Type.IsMap: + return fmt.Sprintf("bstd.MarshalMap(n, b, %s.%s, %s, %s)", + ctr.PrivateName, field.PublicName, g.getElemMarshalFunc(field.Type.MapKeyType), g.getElemMarshalFunc(field.Type.ChildType)) + case field.Type.ExtStructure != "": + if g.IsEnum(field.Type.ExtStructure) { + return fmt.Sprintf("bgenimpl.MarshalEnum(n, b, %s.%s)", + ctr.PrivateName, field.PublicName) + } + + if g.plainGen { + return fmt.Sprintf("%s.%s.MarshalPlain(n, b)", + ctr.PrivateName, field.PublicName) + } + return fmt.Sprintf("%s.%s.marshal(n, b, %d)", + ctr.PrivateName, field.PublicName, field.Id) + default: + return fmt.Sprintf("bstd.Marshal%s%s(n, b, %s.%s)", + field.AppendUnsafeIfPresent(), field.Type.TokenType.String(), ctr.PrivateName, field.PublicName) + } +} - for _, field := range stmt.Fields { - if field.Type.CtrName == "" { - sb.WriteString(fmt.Sprintf(" n = bgenimpl.MarshalTag(n, b, bgenimpl.%s, %d)\n", mapTokenTypeToBgenimplType(field.Type.TokenType), field.Id)) +func (g *GoGen) getElemMarshalFunc(t *parser.Type) string { + switch { + case t.IsArray: + return fmt.Sprintf("func (n int, b []byte, s %s) int { return bstd.MarshalSlice(n, b, s, %s) }", + utils.BencTypeToGolang(t), g.getElemMarshalFunc(t.ChildType)) + case t.IsMap: + return fmt.Sprintf("func (n int, b []byte, s %s) int { return bstd.MarshalMap(n, b, s, %s, %s) }", + utils.BencTypeToGolang(t), g.getElemMarshalFunc(t.MapKeyType), g.getElemMarshalFunc(t.ChildType)) + case t.ExtStructure != "": + if g.IsEnum(t.ExtStructure) { + return "bgenimpl.MarshalEnum" } - sb.WriteString(fmt.Sprintf(" n = %s\n", getMarshalFunc(privStmtName, field, false))) + + return fmt.Sprintf("func (n int, b []byte, s %s) int { return s.MarshalPlain(n, b) }", + utils.ToUpper(t.ExtStructure)) + default: + return "bstd.Marshal" + t.AppendUnsafeIfPresent() + t.TokenType.String() } +} + +func (g *GoGen) GenMarshal() string { + var sb strings.Builder + ctr := g.ctrStmt + + sb.WriteString(fmt.Sprintf("// Marshal - %s\nfunc (%s *%s) Marshal(b []byte) {\n %s.marshal(0, b, 0)\n}\n\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName, ctr.PrivateName)) + + sb.WriteString(fmt.Sprintf("// Nested Marshal - %s\nfunc (%s *%s) marshal(tn int, b []byte, id uint16) (n int) {\n n = bgenimpl.MarshalTag(tn, b, bgenimpl.Container, id)\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName)) + + g.ForEachCtrFields(func(_ int) { + field := g.field + + if !g.IsCtr(field.Type.ExtStructure) { + sb.WriteString(fmt.Sprintf(" n = bgenimpl.MarshalTag(n, b, bgenimpl.%s, %d)\n", + g.mapTokenTypeToBgenimplType(field.Type.TokenType), field.Id)) + } + sb.WriteString(fmt.Sprintf(" n = %s\n", g.getMarshalFunc())) + }) sb.WriteString("\n n += 2\n b[n-2] = 1\n b[n-1] = 1\n return\n}\n\n") return sb.String() } -func mapTokenTypeToBgenimplType(t lexer.Token) string { +func (g *GoGen) GenMarshalPlain() string { + var sb strings.Builder + ctr := g.ctrStmt + + g.plainGen = true + defer func() { g.plainGen = false }() + + sb.WriteString(fmt.Sprintf("// MarshalPlain - %s\nfunc (%s *%s) MarshalPlain(tn int, b []byte) (n int) {\n n = tn\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName)) + + g.ForEachCtrFields(func(_ int) { + sb.WriteString(fmt.Sprintf(" n = %s\n", g.getMarshalFunc())) + }) + + sb.WriteString(" return n\n}\n\n") + return sb.String() +} + +func (g *GoGen) mapTokenTypeToBgenimplType(t lexer.Token) string { switch t { case lexer.INT, lexer.UINT: return "Varint" @@ -233,55 +418,102 @@ func mapTokenTypeToBgenimplType(t lexer.Token) string { } } -func (gen GoGenerator) GenMarshalPlain(stmt *parser.CtrStmt) string { - privStmtName := utils.ToLower(stmt.Name) - publStmtName := utils.ToUpper(stmt.Name) +func (g *GoGen) getUnmarshalFunc() string { + ctr := g.ctrStmt + field := g.field - var sb strings.Builder - sb.WriteString(fmt.Sprintf("// MarshalPlain - %s\nfunc (%s *%s) MarshalPlain(tn int, b []byte) (n int) {\n n = tn\n", stmt.Name, privStmtName, publStmtName)) - for _, field := range stmt.Fields { - sb.WriteString(fmt.Sprintf(" n = %s\n", getMarshalFunc(privStmtName, field, true))) + switch { + case field.Type.IsArray: + return fmt.Sprintf("bstd.UnmarshalSlice[%s](n, b, %s)", + utils.BencTypeToGolang(field.Type.ChildType), g.getElemUnmarshalFunc(field.Type.ChildType)) + case field.Type.IsMap: + return fmt.Sprintf("bstd.UnmarshalMap[%s, %s](n, b, %s, %s)", + utils.BencTypeToGolang(field.Type.MapKeyType), utils.BencTypeToGolang(field.Type.ChildType), g.getElemUnmarshalFunc(field.Type.MapKeyType), g.getElemUnmarshalFunc(field.Type.ChildType)) + case field.Type.ExtStructure != "": + if g.IsEnum(field.Type.ExtStructure) { + return fmt.Sprintf("bgenimpl.UnmarshalEnum[%s](n, b)", field.Type.ExtStructure) + } + if g.plainGen { + return fmt.Sprintf("%s.%s.UnmarshalPlain(n, b)", ctr.PrivateName, field.PublicName) + } + return fmt.Sprintf("bstd.Unmarshal%s%s(n, b)", field.AppendUnsafeIfPresent(), field.Type.TokenType.String()) + default: + return fmt.Sprintf("bstd.Unmarshal%s%s(n, b)", field.AppendUnsafeIfPresent(), field.Type.TokenType.String()) } - sb.WriteString(" return n\n}\n\n") - return sb.String() } -func (gen GoGenerator) GenUnmarshal(stmt *parser.CtrStmt) string { - privStmtName := utils.ToLower(stmt.Name) - publStmtName := utils.ToUpper(stmt.Name) +func (g *GoGen) getElemUnmarshalFunc(t *parser.Type) string { + switch { + case t.IsArray: + return fmt.Sprintf("func (n int, b []byte) (int, %s, error) { return bstd.UnmarshalSlice[%s](n, b, %s) }", + utils.BencTypeToGolang(t), utils.BencTypeToGolang(t.ChildType), g.getElemUnmarshalFunc(t.ChildType)) + case t.IsMap: + return fmt.Sprintf("func (n int, b []byte) (int, %s, error) { return bstd.UnmarshalMap[%s, %s](n, b, %s, %s) }", + utils.BencTypeToGolang(t), utils.BencTypeToGolang(t.MapKeyType), utils.BencTypeToGolang(t.ChildType), g.getElemUnmarshalFunc(t.MapKeyType), g.getElemUnmarshalFunc(t.ChildType)) + case t.ExtStructure != "": + if g.IsEnum(t.ExtStructure) { + return "bgenimpl.UnmarshalEnum" + } + return fmt.Sprintf("func (n int, b []byte, s *%s) (int, error) { return s.UnmarshalPlain(n, b) }", + utils.ToUpper(t.ExtStructure)) + default: + return "bstd.Unmarshal" + t.AppendUnsafeIfPresent() + t.TokenType.String() + } +} +func (g *GoGen) GenUnmarshal() string { var sb strings.Builder - sb.WriteString(fmt.Sprintf("// Unmarshal - %s\nfunc (%s *%s) Unmarshal(b []byte) (err error) {\n _, err = %s.unmarshal(0, b, []uint16{}, 0)\n return\n}\n\n", stmt.Name, privStmtName, publStmtName, privStmtName)) - sb.WriteString(fmt.Sprintf("// Nested Unmarshal - %s\nfunc (%s *%s) unmarshal(tn int, b []byte, r []uint16, id uint16) (n int, err error) {\n var ok bool\n if n, ok, err = bgenimpl.HandleCompatibility(tn, b, r, id); !ok {\n if err == bgenimpl.ErrEof {\n return n, nil\n }\n return\n }\n", stmt.Name, privStmtName, publStmtName)) - - for _, field := range stmt.Fields { - fieldName := utils.ToUpper(field.Name) - if field.Type.CtrName != "" { - sb.WriteString(fmt.Sprintf(" if n, err = %s.%s.unmarshal(n, b, %sRIds, %d); err != nil {\n return\n }\n", privStmtName, fieldName, privStmtName, field.Id)) - continue + ctr := g.ctrStmt + + sb.WriteString(fmt.Sprintf("// Unmarshal - %s\nfunc (%s *%s) Unmarshal(b []byte) (err error) {\n _, err = %s.unmarshal(0, b, []uint16{}, 0)\n return\n}\n\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName, ctr.PrivateName)) + + sb.WriteString(fmt.Sprintf("// Nested Unmarshal - %s\nfunc (%s *%s) unmarshal(tn int, b []byte, r []uint16, id uint16) (n int, err error) {\n var ok bool\n if n, ok, err = bgenimpl.HandleCompatibility(tn, b, r, id); !ok {\n if err == bgenimpl.ErrEof {\n return n, nil\n }\n return\n }\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName)) + + g.ForEachCtrFields(func(_ int) { + field := g.field + + if g.IsCtr(field.Type.ExtStructure) { + sb.WriteString(fmt.Sprintf(" if n, err = %s.%s.unmarshal(n, b, %sRIds, %d); err != nil {\n return\n }\n", + ctr.PrivateName, field.PublicName, ctr.PrivateName, field.Id)) + return } - sb.WriteString(fmt.Sprintf(" if n, ok, err = bgenimpl.HandleCompatibility(n, b, %sRIds, %d); err != nil {\n if err == bgenimpl.ErrEof {\n return n, nil\n }\n return\n }\n", privStmtName, field.Id)) - sb.WriteString(fmt.Sprintf(" if ok {\n if n, %s.%s, err = %s; err != nil {\n return\n }\n }\n", privStmtName, fieldName, getUnmarshalFunc(privStmtName, field, false))) - } + + sb.WriteString(fmt.Sprintf(" if n, ok, err = bgenimpl.HandleCompatibility(n, b, %sRIds, %d); err != nil {\n if err == bgenimpl.ErrEof {\n return n, nil\n }\n return\n }\n", + ctr.PrivateName, field.Id)) + + sb.WriteString(fmt.Sprintf(" if ok {\n if n, %s.%s, err = %s; err != nil {\n return\n }\n }\n", + ctr.PrivateName, field.PublicName, g.getUnmarshalFunc())) + }) sb.WriteString(" n += 2\n return\n}\n\n") return sb.String() } -func (gen GoGenerator) GenUnmarshalPlain(stmt *parser.CtrStmt) string { - privStmtName := utils.ToLower(stmt.Name) - publStmtName := utils.ToUpper(stmt.Name) - +func (g *GoGen) GenUnmarshalPlain() string { var sb strings.Builder - sb.WriteString(fmt.Sprintf("// UnmarshalPlain - %s\nfunc (%s *%s) UnmarshalPlain(tn int, b []byte) (n int, err error) {\n n = tn\n", stmt.Name, privStmtName, publStmtName)) - for _, field := range stmt.Fields { - if field.Type.CtrName != "" { - sb.WriteString(fmt.Sprintf(" if n, err = %s; err != nil {\n return\n }\n", getUnmarshalFunc(privStmtName, field, true))) - continue + ctr := g.ctrStmt + + g.plainGen = true + defer func() { g.plainGen = false }() + + sb.WriteString(fmt.Sprintf("// UnmarshalPlain - %s\nfunc (%s *%s) UnmarshalPlain(tn int, b []byte) (n int, err error) {\n n = tn\n", + ctr.DefaultName, ctr.PrivateName, ctr.PublicName)) + + g.ForEachCtrFields(func(_ int) { + field := g.field + + if g.IsCtr(field.Type.ExtStructure) { + sb.WriteString(fmt.Sprintf(" if n, err = %s; err != nil {\n return\n }\n", + g.getUnmarshalFunc())) + return } - sb.WriteString(fmt.Sprintf(" if n, %s.%s, err = %s; err != nil {\n return\n }\n", privStmtName, utils.ToUpper(field.Name), getUnmarshalFunc(privStmtName, field, true))) - } + sb.WriteString(fmt.Sprintf(" if n, %s.%s, err = %s; err != nil {\n return\n }\n", + ctr.PrivateName, field.PublicName, g.getUnmarshalFunc())) + }) + sb.WriteString(" return\n}\n\n") return sb.String() } diff --git a/cmd/bencgen/lexer/lexer.go b/cmd/bencgen/lexer/lexer.go index 1e16b17..434dee5 100644 --- a/cmd/bencgen/lexer/lexer.go +++ b/cmd/bencgen/lexer/lexer.go @@ -50,6 +50,7 @@ const ( OPEN_ARROW // < CLOSE_ARROW // > + ENUM // enum CTR // container COMMA // , EQUALS // = @@ -64,6 +65,7 @@ var tokens = []string{ RESERVED: "Reserved", IDENT: "Identifier", CTR: "Container", + ENUM: "Enum", INT64: "Int64", INT32: "Int32", @@ -103,6 +105,7 @@ var keywords = map[string]Token{ "reserved": RESERVED, "header": HEADER, "ctr": CTR, + "enum": ENUM, "int64": INT64, "int32": INT32, diff --git a/cmd/bencgen/main.go b/cmd/bencgen/main.go index c110413..3437add 100644 --- a/cmd/bencgen/main.go +++ b/cmd/bencgen/main.go @@ -41,8 +41,8 @@ func main() { return } - lang := codegens.GeneratorLanguage(*lFlag) - generator := codegens.NewGenerator(lang, *iFlag) + lang := codegens.GenLang(*lFlag) + generator := codegens.NewGen(lang, *iFlag) if generator == nil { printError("Unknown language provided.") return diff --git a/cmd/bencgen/parser/parser.go b/cmd/bencgen/parser/parser.go index d940696..205fe77 100644 --- a/cmd/bencgen/parser/parser.go +++ b/cmd/bencgen/parser/parser.go @@ -68,7 +68,7 @@ func (p *Parser) expectType() *Type { case p.match(lexer.IDENT): ctrName := p.lit p.nextToken() - return &Type{CtrName: ctrName} + return &Type{ExtStructure: ctrName} case p.match(lexer.UNSAFE): p.nextToken() @@ -119,13 +119,13 @@ type Node interface{} type ( Type struct { - TokenType lexer.Token - MapKeyType *Type - ChildType *Type - CtrName string - IsUnsafe bool - IsArray bool - IsMap bool + TokenType lexer.Token + MapKeyType *Type + ChildType *Type + ExtStructure string `json:"ctrName"` + IsUnsafe bool + IsArray bool + IsMap bool } HeaderStmt struct { Name string @@ -135,6 +135,10 @@ type ( Fields []Field ReservedIds []uint16 } + EnumStmt struct { + Name string + Fields []string + } Field struct { Id uint16 Name string @@ -142,18 +146,15 @@ type ( } ) -func (t *Type) GetUnsafeStr() string { - if t.IsUnsafe { - return "Unsafe" +func (t *Type) AppendUnsafeIfPresent() string { + if !t.IsUnsafe { + return "" } - return "" + return "Unsafe" } -func (f *Field) GetUnsafeStr() string { - if f.Type.IsUnsafe { - return "Unsafe" - } - return "" +func (f *Field) AppendUnsafeIfPresent() string { + return f.Type.AppendUnsafeIfPresent() } func (p *Parser) Parse() []Node { @@ -171,8 +172,10 @@ func (p *Parser) parseStatement() Node { return p.parseHeaderStmt() case p.match(lexer.CTR): return p.parseCtrStmt() + case p.match(lexer.ENUM): + return p.parseEnumStmt() default: - p.error(fmt.Sprintf("Unexpected token: `%s`. Expected: `Container or Header`", p.token)) + p.error(fmt.Sprintf("Unexpected token: `%s`. Expected: `Container, Enum or Header`", p.token)) return nil } } @@ -198,6 +201,35 @@ func (p *Parser) parseCtrStmt() Node { return &CtrStmt{Name: name, ReservedIds: reservedIds, Fields: fields} } +func (p *Parser) parseEnumStmt() Node { + p.expect(lexer.ENUM) + name := p.lit + p.expect(lexer.IDENT) + p.expect(lexer.OPEN_BRACE) + + fields := p.parseEnumFields() + + p.expect(lexer.CLOSE_BRACE) + return &EnumStmt{Name: name, Fields: fields} +} + +func (p *Parser) parseEnumFields() []string { + var fields []string + for !p.match(lexer.CLOSE_BRACE) { + fields = append(fields, p.parseEnumField()) + } + return fields +} + +func (p *Parser) parseEnumField() string { + ident := p.lit + p.expect(lexer.IDENT) + if !p.match(lexer.CLOSE_BRACE) { + p.expect(lexer.COMMA) + } + return ident +} + func (p *Parser) parseReservedIds() []uint16 { if p.match(lexer.RESERVED) { p.nextToken() diff --git a/cmd/bencgen/utils/utils.go b/cmd/bencgen/utils/utils.go index 793a10d..f4b9e84 100644 --- a/cmd/bencgen/utils/utils.go +++ b/cmd/bencgen/utils/utils.go @@ -36,8 +36,8 @@ func formatTypeHelper(t *parser.Type, useGoFormat bool) string { return "<" + keyFormat + ", " + valueFormat + ">" } - if t.CtrName != "" { - return t.CtrName + if t.ExtStructure != "" { + return t.ExtStructure } if useGoFormat { @@ -50,19 +50,19 @@ func CompareTypes(t1 *parser.Type, t2 *parser.Type) bool { return compareTypes(t1, t2) } -func FindUndeclaredContainers(ctrDeclarations []string, t *parser.Type) (string, bool) { - if t.CtrName != "" && !slices.Contains(ctrDeclarations, t.CtrName) { - return t.CtrName, true +func FindUndeclaredContainersOrEnums(declarations []string, t *parser.Type) (string, bool) { + if t.ExtStructure != "" && !slices.Contains(declarations, t.ExtStructure) { + return t.ExtStructure, true } if t.ChildType != nil { - if ctr, notFound := FindUndeclaredContainers(ctrDeclarations, t.ChildType); notFound { + if ctr, notFound := FindUndeclaredContainersOrEnums(declarations, t.ChildType); notFound { return ctr, true } } if t.MapKeyType != nil { - if ctr, notFound := FindUndeclaredContainers(ctrDeclarations, t.MapKeyType); notFound { + if ctr, notFound := FindUndeclaredContainersOrEnums(declarations, t.MapKeyType); notFound { return ctr, true } } @@ -78,7 +78,7 @@ func compareTypes(t1 *parser.Type, t2 *parser.Type) bool { return t1.IsArray == t2.IsArray && t1.IsMap == t2.IsMap && t1.TokenType == t2.TokenType && - t1.CtrName == t2.CtrName && + t1.ExtStructure == t2.ExtStructure && compareTypes(t1.MapKeyType, t2.MapKeyType) && compareTypes(t1.ChildType, t2.ChildType) } diff --git a/impl/gen/README.md b/impl/gen/README.md index 056f02d..c08e157 100644 --- a/impl/gen/README.md +++ b/impl/gen/README.md @@ -1,12 +1,15 @@ # bgen-impl -The implementation for [bencgen](../../cmd/bencgen/README.md). Contains various methods for handling forward and backward compatibility. +The implementation for [bencgen](../../cmd/bencgen/README.md). Contains various methods for handling forward and backward compatibility. + #### WARNING: Should only be used in `bencgen`-generated code. ## Installation + ```bash go get github.com/deneonet/benc/impl/gen ``` ## Tests -Code coverage of `bencgen.go` is 100% \ No newline at end of file + +Code coverage of `bencgen.go` is 100% diff --git a/impl/gen/bencgen.go b/impl/gen/bencgen.go index a53ff75..247d0d0 100644 --- a/impl/gen/bencgen.go +++ b/impl/gen/bencgen.go @@ -145,3 +145,20 @@ func UnmarshalTag(n int, b []byte) (int, uint16, byte, error) { } return n, uint16(b[n-1]), typ, nil } + +func SkipEnum(n int, b []byte) (int, error) { + return bstd.SkipVarint(n, b) +} + +func SizeEnum[T ~int](v T) int { + return bstd.SizeInt(int(v)) +} + +func MarshalEnum[T ~int](n int, b []byte, v T) int { + return bstd.MarshalInt(n, b, int(v)) +} + +func UnmarshalEnum[T ~int](n int, b []byte) (int, T, error) { + n, v, err := bstd.UnmarshalInt(n, b) + return n, T(v), err +} diff --git a/impl/gen/bencgen_test.go b/impl/gen/bencgen_test.go index 2fea00c..23c6860 100644 --- a/impl/gen/bencgen_test.go +++ b/impl/gen/bencgen_test.go @@ -1,6 +1,9 @@ package bgenimpl import ( + "encoding/binary" + "errors" + "strconv" "testing" "github.com/deneonet/benc" @@ -298,3 +301,71 @@ func TestHandleCompatibility_Types(t *testing.T) { t.Fatal("expected ErrInvalidType") } } + +var maxVarintLenMap = map[int]int{ + 64: binary.MaxVarintLen64, + 32: binary.MaxVarintLen32, +} + +var maxVarintLen = maxVarintLenMap[strconv.IntSize] + +func TestEnums(t *testing.T) { + v := 150 + size := SizeEnum(v) + if size != 2 { + t.Errorf("expected size 2, got %d", size) + } + + buf := []byte{172, 2} + n, err := SkipEnum(0, buf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if n != 2 { + t.Errorf("expected offset 2, got %d", n) + } + + buf = []byte{172} + _, err = SkipEnum(0, buf) + if !errors.Is(err, benc.ErrBufTooSmall) { + t.Errorf("expected ErrBufTooSmall, got %v", err) + } + + buf = make([]byte, 10) + n = MarshalEnum(0, buf, 150) + if n != 2 { + t.Errorf("expected offset 2, got %d", n) + } + t.Log(buf[1]) + if buf[0] != 172 || buf[1] != 2 { + t.Errorf("unexpected buffer contents: %v", buf[:n]) + } + + buf = []byte{172, 2} + n, v, err = UnmarshalEnum[int](0, buf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if n != 2 { + t.Errorf("expected offset 2, got %d", n) + } + if v != 150 { + t.Errorf("expected value 150, got %d", v) + } + + buf = []byte{172} + _, _, err = UnmarshalEnum[int](0, buf) + if !errors.Is(err, benc.ErrBufTooSmall) { + t.Errorf("expected ErrBufTooSmall, got %v", err) + } + + buf = make([]byte, maxVarintLen+1) + for i := 0; i < maxVarintLen+1; i++ { + buf[i] = 0x80 + } + buf[maxVarintLen] = 0x02 + _, _, err = UnmarshalEnum[int](0, buf) + if !errors.Is(err, benc.ErrOverflow) { + t.Errorf("expected ErrOverflow, got %v", err) + } +} diff --git a/std/bstd_test.go b/std/bstd_test.go index 87e64b5..2782bee 100644 --- a/std/bstd_test.go +++ b/std/bstd_test.go @@ -11,8 +11,7 @@ import ( "github.com/deneonet/benc" ) -func SizeAll(sizers ...func() int) int { - s := 0 +func SizeAll(sizers ...func() int) (s int) { for _, sizer := range sizers { ts := sizer() if ts == 0 { @@ -20,33 +19,35 @@ func SizeAll(sizers ...func() int) int { } s += ts } - return s + + return } -func SkipAll(b []byte, skipers ...func(n int, b []byte) (int, error)) error { +func SkipAll(b []byte, skipers ...func(n int, b []byte) (int, error)) (err error) { n := 0 - var err error + for i, skiper := range skipers { n, err = skiper(n, b) if err != nil { return fmt.Errorf("(skip) at idx %d: error: %s", i, err.Error()) } } + if n != len(b) { - return errors.New("skip failed: something doesn't match in the marshal- and skip progrss") + return errors.New("skip failed: something doesn't match in the marshal- and skip progress") } return nil } func SkipOnce_Verify(b []byte, skiper func(n int, b []byte) (int, error)) error { - n := 0 - var err error - n, err = skiper(n, b) + n, err := skiper(0, b) + if err != nil { return fmt.Errorf("skip: error: %s", err.Error()) } + if n != len(b) { - return errors.New("skip failed: something doesn't match in the marshal- and skip progrss") + return errors.New("skip failed: something doesn't match in the marshal- and skip progress") } return nil } @@ -54,6 +55,7 @@ func SkipOnce_Verify(b []byte, skiper func(n int, b []byte) (int, error)) error func MarshalAll(s int, values []any, marshals ...func(n int, b []byte, v any) int) ([]byte, error) { n := 0 b := make([]byte, s) + for i, marshal := range marshals { n = marshal(n, b, values[i]) if n == 0 { @@ -61,16 +63,21 @@ func MarshalAll(s int, values []any, marshals ...func(n int, b []byte, v any) in return nil, nil } } + if n != len(b) { - return nil, errors.New("marshal failed: something doesn't match in the marshal- and size progrss") + return nil, errors.New("marshal failed: something doesn't match in the marshal- and size progress") } + return b, nil } -func UnmarshalAll_Verify(b []byte, values []any, unmarshals ...func(n int, b []byte) (int, any, error)) error { +func UnmarshalAll(b []byte, values []any, unmarshals ...func(n int, b []byte) (int, any, error)) error { n := 0 - var v any - var err error + var ( + v any + err error + ) + for i, unmarshal := range unmarshals { n, v, err = unmarshal(n, b) if err != nil { @@ -80,9 +87,11 @@ func UnmarshalAll_Verify(b []byte, values []any, unmarshals ...func(n int, b []b return fmt.Errorf("(unmarshal) at idx %d: no match: expected %v, got %v --- (%T - %T)", i, values[i], v, values[i], v) } } + if n != len(b) { return errors.New("unmarshal failed: something doesn't match in the marshal- and unmarshal progrss") } + return nil } @@ -115,14 +124,32 @@ func TestDataTypes(t *testing.T) { } testBs := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - s := SizeAll(SizeBool, SizeBool, SizeByte, SizeFloat32, SizeFloat64, func() int { return SizeInt(math.MaxInt) }, SizeInt16, SizeInt32, SizeInt64, func() int { return SizeUint(math.MaxUint) }, SizeUint16, SizeUint32, SizeUint64, - sizeTestStr, sizeTestStr, func() int { - return SizeBytes(testBs) - }) - - values := []any{true, false, byte(128), rand.Float32(), rand.Float64(), int(math.MaxInt), int16(16), rand.Int31(), rand.Int63(), uint(math.MaxUint), uint16(160), rand.Uint32(), rand.Uint64(), testStr, testStr, testBs} - buf, err := MarshalAll(s, values, - func(n int, b []byte, v any) int { return MarshalBool(n, b, v.(bool)) }, + sizeTestBs := func() int { + return SizeBytes(testBs) + } + + values := []any{ + true, + byte(128), + rand.Float32(), + rand.Float64(), + int(math.MaxInt), + int16(16), + rand.Int31(), + rand.Int63(), + uint(math.MaxUint), + uint16(160), + rand.Uint32(), + rand.Uint64(), + testStr, + testStr, + testBs, + } + + s := SizeAll(SizeBool, SizeByte, SizeFloat32, SizeFloat64, func() int { return SizeInt(math.MaxInt) }, SizeInt16, SizeInt32, SizeInt64, func() int { return SizeUint(math.MaxUint) }, SizeUint16, SizeUint32, SizeUint64, + sizeTestStr, sizeTestStr, sizeTestBs) + + b, err := MarshalAll(s, values, func(n int, b []byte, v any) int { return MarshalBool(n, b, v.(bool)) }, func(n int, b []byte, v any) int { return MarshalByte(n, b, v.(byte)) }, func(n int, b []byte, v any) int { return MarshalFloat32(n, b, v.(float32)) }, @@ -139,16 +166,16 @@ func TestDataTypes(t *testing.T) { func(n int, b []byte, v any) int { return MarshalUnsafeString(n, b, v.(string)) }, func(n int, b []byte, v any) int { return MarshalBytes(n, b, v.([]byte)) }, ) + if err != nil { t.Fatal(err.Error()) } - if err = SkipAll(buf, SkipBool, SkipBool, SkipByte, SkipFloat32, SkipFloat64, SkipVarint, SkipInt16, SkipInt32, SkipInt64, SkipVarint, SkipUint16, SkipUint32, SkipUint64, SkipString, SkipString, SkipBytes); err != nil { + if err = SkipAll(b, SkipBool, SkipByte, SkipFloat32, SkipFloat64, SkipVarint, SkipInt16, SkipInt32, SkipInt64, SkipVarint, SkipUint16, SkipUint32, SkipUint64, SkipString, SkipString, SkipBytes); err != nil { t.Fatal(err.Error()) } - if err = UnmarshalAll_Verify(buf, values, - func(n int, b []byte) (int, any, error) { return UnmarshalBool(n, b) }, + if err = UnmarshalAll(b, values, func(n int, b []byte) (int, any, error) { return UnmarshalBool(n, b) }, func(n int, b []byte) (int, any, error) { return UnmarshalByte(n, b) }, func(n int, b []byte) (int, any, error) { return UnmarshalFloat32(n, b) }, diff --git a/testing/unsignedInt/main_uint_test.go b/testing/others/main_others_test.go similarity index 78% rename from testing/unsignedInt/main_uint_test.go rename to testing/others/main_others_test.go index 9faec58..187fcb2 100644 --- a/testing/unsignedInt/main_uint_test.go +++ b/testing/others/main_others_test.go @@ -1,6 +1,6 @@ -//go:generate bencgen --in ../schemas/uint.benc --out ./ --file uint_test --lang go +//go:generate bencgen --in ../schemas/others.benc --out ./ --file others_test --lang go -package unsignedInt +package others import ( "math/rand" @@ -21,7 +21,7 @@ func TestUint(t *testing.T) { ui64Map[rand.Uint64()] = rand.Uint32() ui64Map[rand.Uint64()] = rand.Uint32() - data := UintTest{ + data := OthersTest{ Ui64: ui64, Ui32: ui32, Ui16: ui16, @@ -29,12 +29,15 @@ func TestUint(t *testing.T) { Ui64Arr: ui64Arr, Ui64Map: ui64Map, + + ExampleEnum: ExampleEnumOne, + ExampleEnum2: ExampleEnum2Six, } buf := make([]byte, data.Size()) data.Marshal(buf) - var deserData UintTest + var deserData OthersTest err := deserData.Unmarshal(buf) if err != nil { t.Fatal(err) diff --git a/testing/others/others_test.go b/testing/others/others_test.go new file mode 100644 index 0000000..1b35c9d --- /dev/null +++ b/testing/others/others_test.go @@ -0,0 +1,260 @@ +// Code generated by bencgen go. DO NOT EDIT. +// source: ../schemas/others.benc + +package others + +import ( + "github.com/deneonet/benc/std" + "github.com/deneonet/benc/impl/gen" +) + +// Enum - ExampleEnum +type ExampleEnum int +const ( + ExampleEnumOne ExampleEnum = iota + ExampleEnumTwo + ExampleEnumThree + ExampleEnumFour +) + +// Enum - ExampleEnum2 +type ExampleEnum2 int +const ( + ExampleEnum2Five ExampleEnum2 = iota + ExampleEnum2Six +) + +// Struct - OthersTest +type OthersTest struct { + Ui64 uint64 + Ui64Arr []uint64 + Ui64Map map[uint64]uint32 + Ui32 uint32 + Ui16 uint16 + Ui uint + ExampleEnum ExampleEnum + ExampleEnum2 ExampleEnum2 +} + +// Reserved Ids - OthersTest +var othersTestRIds = []uint16{} + +// Size - OthersTest +func (othersTest *OthersTest) Size() int { + return othersTest.size(0) +} + +// Nested Size - OthersTest +func (othersTest *OthersTest) size(id uint16) (s int) { + s += bstd.SizeUint64() + 2 + s += bstd.SizeSlice(othersTest.Ui64Arr, bstd.SizeUint64) + 2 + s += bstd.SizeMap(othersTest.Ui64Map, bstd.SizeUint64, bstd.SizeUint32) + 2 + s += bstd.SizeUint32() + 2 + s += bstd.SizeUint16() + 2 + s += bstd.SizeUint(othersTest.Ui) + 2 + s += bgenimpl.SizeEnum(othersTest.ExampleEnum) + 2 + s += bgenimpl.SizeEnum(othersTest.ExampleEnum2) + 2 + + if id > 255 { + s += 5 + return + } + s += 4 + return +} + +// SizePlain - OthersTest +func (othersTest *OthersTest) SizePlain() (s int) { + s += bstd.SizeUint64() + s += bstd.SizeSlice(othersTest.Ui64Arr, bstd.SizeUint64) + s += bstd.SizeMap(othersTest.Ui64Map, bstd.SizeUint64, bstd.SizeUint32) + s += bstd.SizeUint32() + s += bstd.SizeUint16() + s += bstd.SizeUint(othersTest.Ui) + s += bgenimpl.SizeEnum(othersTest.ExampleEnum) + s += bgenimpl.SizeEnum(othersTest.ExampleEnum2) + return +} + +// Marshal - OthersTest +func (othersTest *OthersTest) Marshal(b []byte) { + othersTest.marshal(0, b, 0) +} + +// Nested Marshal - OthersTest +func (othersTest *OthersTest) marshal(tn int, b []byte, id uint16) (n int) { + n = bgenimpl.MarshalTag(tn, b, bgenimpl.Container, id) + n = bgenimpl.MarshalTag(n, b, bgenimpl.Fixed64, 1) + n = bstd.MarshalUint64(n, b, othersTest.Ui64) + n = bgenimpl.MarshalTag(n, b, bgenimpl.ArrayMap, 2) + n = bstd.MarshalSlice(n, b, othersTest.Ui64Arr, bstd.MarshalUint64) + n = bgenimpl.MarshalTag(n, b, bgenimpl.ArrayMap, 3) + n = bstd.MarshalMap(n, b, othersTest.Ui64Map, bstd.MarshalUint64, bstd.MarshalUint32) + n = bgenimpl.MarshalTag(n, b, bgenimpl.Fixed32, 4) + n = bstd.MarshalUint32(n, b, othersTest.Ui32) + n = bgenimpl.MarshalTag(n, b, bgenimpl.Fixed16, 5) + n = bstd.MarshalUint16(n, b, othersTest.Ui16) + n = bgenimpl.MarshalTag(n, b, bgenimpl.Varint, 7) + n = bstd.MarshalUint(n, b, othersTest.Ui) + n = bgenimpl.MarshalTag(n, b, bgenimpl.ArrayMap, 8) + n = bgenimpl.MarshalEnum(n, b, othersTest.ExampleEnum) + n = bgenimpl.MarshalTag(n, b, bgenimpl.ArrayMap, 9) + n = bgenimpl.MarshalEnum(n, b, othersTest.ExampleEnum2) + + n += 2 + b[n-2] = 1 + b[n-1] = 1 + return +} + +// MarshalPlain - OthersTest +func (othersTest *OthersTest) MarshalPlain(tn int, b []byte) (n int) { + n = tn + n = bstd.MarshalUint64(n, b, othersTest.Ui64) + n = bstd.MarshalSlice(n, b, othersTest.Ui64Arr, bstd.MarshalUint64) + n = bstd.MarshalMap(n, b, othersTest.Ui64Map, bstd.MarshalUint64, bstd.MarshalUint32) + n = bstd.MarshalUint32(n, b, othersTest.Ui32) + n = bstd.MarshalUint16(n, b, othersTest.Ui16) + n = bstd.MarshalUint(n, b, othersTest.Ui) + n = bgenimpl.MarshalEnum(n, b, othersTest.ExampleEnum) + n = bgenimpl.MarshalEnum(n, b, othersTest.ExampleEnum2) + return n +} + +// Unmarshal - OthersTest +func (othersTest *OthersTest) Unmarshal(b []byte) (err error) { + _, err = othersTest.unmarshal(0, b, []uint16{}, 0) + return +} + +// Nested Unmarshal - OthersTest +func (othersTest *OthersTest) unmarshal(tn int, b []byte, r []uint16, id uint16) (n int, err error) { + var ok bool + if n, ok, err = bgenimpl.HandleCompatibility(tn, b, r, id); !ok { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 1); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.Ui64, err = bstd.UnmarshalUint64(n, b); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 2); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.Ui64Arr, err = bstd.UnmarshalSlice[uint64](n, b, bstd.UnmarshalUint64); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 3); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.Ui64Map, err = bstd.UnmarshalMap[uint64, uint32](n, b, bstd.UnmarshalUint64, bstd.UnmarshalUint32); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 4); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.Ui32, err = bstd.UnmarshalUint32(n, b); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 5); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.Ui16, err = bstd.UnmarshalUint16(n, b); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 7); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.Ui, err = bstd.UnmarshalUint(n, b); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 8); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.ExampleEnum, err = bgenimpl.UnmarshalEnum[ExampleEnum](n, b); err != nil { + return + } + } + if n, ok, err = bgenimpl.HandleCompatibility(n, b, othersTestRIds, 9); err != nil { + if err == bgenimpl.ErrEof { + return n, nil + } + return + } + if ok { + if n, othersTest.ExampleEnum2, err = bgenimpl.UnmarshalEnum[ExampleEnum2](n, b); err != nil { + return + } + } + n += 2 + return +} + +// UnmarshalPlain - OthersTest +func (othersTest *OthersTest) UnmarshalPlain(tn int, b []byte) (n int, err error) { + n = tn + if n, othersTest.Ui64, err = bstd.UnmarshalUint64(n, b); err != nil { + return + } + if n, othersTest.Ui64Arr, err = bstd.UnmarshalSlice[uint64](n, b, bstd.UnmarshalUint64); err != nil { + return + } + if n, othersTest.Ui64Map, err = bstd.UnmarshalMap[uint64, uint32](n, b, bstd.UnmarshalUint64, bstd.UnmarshalUint32); err != nil { + return + } + if n, othersTest.Ui32, err = bstd.UnmarshalUint32(n, b); err != nil { + return + } + if n, othersTest.Ui16, err = bstd.UnmarshalUint16(n, b); err != nil { + return + } + if n, othersTest.Ui, err = bstd.UnmarshalUint(n, b); err != nil { + return + } + if n, othersTest.ExampleEnum, err = bgenimpl.UnmarshalEnum[ExampleEnum](n, b); err != nil { + return + } + if n, othersTest.ExampleEnum2, err = bgenimpl.UnmarshalEnum[ExampleEnum2](n, b); err != nil { + return + } + return +} + diff --git a/testing/person/person2_test.go b/testing/person/person2_test.go index 561821d..dddd7ce 100644 --- a/testing/person/person2_test.go +++ b/testing/person/person2_test.go @@ -1,4 +1,4 @@ -// Code generated by bencgen golang. DO NOT EDIT. +// Code generated by bencgen go. DO NOT EDIT. // source: ../schemas/person2.benc package person diff --git a/testing/person/person_test.go b/testing/person/person_test.go index f63d5ab..bb08c7a 100644 --- a/testing/person/person_test.go +++ b/testing/person/person_test.go @@ -1,4 +1,4 @@ -// Code generated by bencgen golang. DO NOT EDIT. +// Code generated by bencgen go. DO NOT EDIT. // source: ../schemas/person.benc package person diff --git a/testing/schemas/others.benc b/testing/schemas/others.benc new file mode 100644 index 0000000..ece4988 --- /dev/null +++ b/testing/schemas/others.benc @@ -0,0 +1,29 @@ +header others; + +enum ExampleEnum { + One, + Two, + Three, + Four, +} + +enum ExampleEnum2 { + Five, + Six +} + +ctr OthersTest { + uint64 ui64 = 1; + []uint64 ui64Arr = 2; + ui64Map = 3; + + uint32 ui32 = 4; + uint16 ui16 = 5; + uint ui = 7; + + ExampleEnum exampleEnum = 8; + ExampleEnum2 exampleEnum2 = 9; +} + +# DO NOT EDIT. +# [meta_s] eyJtc2dzIjp7Ik90aGVyc1Rlc3QiOnsicklkcyI6bnVsbCwiZmllbGRzIjp7IjEiOnsiSWQiOjEsIk5hbWUiOiJ1aTY0IiwiVHlwZSI6eyJUb2tlblR5cGUiOjEwLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMiI6eyJJZCI6MiwiTmFtZSI6InVpNjRBcnIiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjp7IlRva2VuVHlwZSI6MTAsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX0sImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOnRydWUsIklzTWFwIjpmYWxzZX19LCIzIjp7IklkIjozLCJOYW1lIjoidWk2NE1hcCIsIlR5cGUiOnsiVG9rZW5UeXBlIjowLCJNYXBLZXlUeXBlIjp7IlRva2VuVHlwZSI6MTAsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX0sIkNoaWxkVHlwZSI6eyJUb2tlblR5cGUiOjExLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9LCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOnRydWV9fSwiNCI6eyJJZCI6NCwiTmFtZSI6InVpMzIiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTEsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCI1Ijp7IklkIjo1LCJOYW1lIjoidWkxNiIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxMiwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjciOnsiSWQiOjcsIk5hbWUiOiJ1aSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxMywiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjgiOnsiSWQiOjgsIk5hbWUiOiJleGFtcGxlRW51bSIsIlR5cGUiOnsiVG9rZW5UeXBlIjowLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiJFeGFtcGxlRW51bSIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCI5Ijp7IklkIjo5LCJOYW1lIjoiZXhhbXBsZUVudW0yIiwiVHlwZSI6eyJUb2tlblR5cGUiOjAsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IkV4YW1wbGVFbnVtMiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX19fQ== [meta_e] \ No newline at end of file diff --git a/testing/schemas/person.benc b/testing/schemas/person.benc index e432656..3cc397f 100644 --- a/testing/schemas/person.benc +++ b/testing/schemas/person.benc @@ -19,4 +19,4 @@ ctr Parents { } # DO NOT EDIT. -# [meta_s] eyJtc2dzIjp7IkNoaWxkIjp7InJJZHMiOm51bGwsImZpZWxkcyI6eyIxIjp7IklkIjoxLCJOYW1lIjoiYWdlIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE5LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMiI6eyJJZCI6MiwiTmFtZSI6Im5hbWUiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTUsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiQ3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCIzIjp7IklkIjozLCJOYW1lIjoicGFyZW50cyIsIlR5cGUiOnsiVG9rZW5UeXBlIjowLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiJQYXJlbnRzIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX19fSwiUGFyZW50cyI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6Im1vdGhlciIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxNSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJmYXRoZXIiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTUsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiQ3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX0sIlBlcnNvbiI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6ImFnZSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxOSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJuYW1lIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE1LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMyI6eyJJZCI6MywiTmFtZSI6InBhcmVudHMiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiUGFyZW50cyIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCI0Ijp7IklkIjo0LCJOYW1lIjoiY2hpbGQiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiQ2hpbGQiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fX19fX0= [meta_e] \ No newline at end of file +# [meta_s] eyJtc2dzIjp7IkNoaWxkIjp7InJJZHMiOm51bGwsImZpZWxkcyI6eyIxIjp7IklkIjoxLCJOYW1lIjoiYWdlIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE5LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMiI6eyJJZCI6MiwiTmFtZSI6Im5hbWUiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTUsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCIzIjp7IklkIjozLCJOYW1lIjoicGFyZW50cyIsIlR5cGUiOnsiVG9rZW5UeXBlIjowLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiJQYXJlbnRzIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX19fSwiUGFyZW50cyI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6Im1vdGhlciIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxNSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJmYXRoZXIiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTUsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX0sIlBlcnNvbiI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6ImFnZSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxOSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJuYW1lIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE1LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMyI6eyJJZCI6MywiTmFtZSI6InBhcmVudHMiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiUGFyZW50cyIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCI0Ijp7IklkIjo0LCJOYW1lIjoiY2hpbGQiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiQ2hpbGQiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fX19fX0= [meta_e] \ No newline at end of file diff --git a/testing/schemas/person2.benc b/testing/schemas/person2.benc index 25b8d85..0069aa0 100644 --- a/testing/schemas/person2.benc +++ b/testing/schemas/person2.benc @@ -20,4 +20,4 @@ ctr Parents2 { } # DO NOT EDIT. -# [meta_s] eyJtc2dzIjp7IkNoaWxkMiI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6ImFnZSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxOSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJuYW1lIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE1LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMyI6eyJJZCI6MywiTmFtZSI6InBhcmVudHMiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiUGFyZW50czIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fX19LCJQYXJlbnRzMiI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6Im1vdGhlciIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxNSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJmYXRoZXIiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTUsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiQ3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX0sIlBlcnNvbjIiOnsicklkcyI6WzNdLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6ImFnZSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxOSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJuYW1lIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE1LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiNCI6eyJJZCI6NCwiTmFtZSI6ImNoaWxkIiwiVHlwZSI6eyJUb2tlblR5cGUiOjAsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiQ3RyTmFtZSI6IkNoaWxkMiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX19fQ== [meta_e] \ No newline at end of file +# [meta_s] eyJtc2dzIjp7IkNoaWxkMiI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6ImFnZSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxOSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJuYW1lIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE1LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiMyI6eyJJZCI6MywiTmFtZSI6InBhcmVudHMiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiUGFyZW50czIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fX19LCJQYXJlbnRzMiI6eyJySWRzIjpudWxsLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6Im1vdGhlciIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxNSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJmYXRoZXIiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTUsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX0sIlBlcnNvbjIiOnsicklkcyI6WzNdLCJmaWVsZHMiOnsiMSI6eyJJZCI6MSwiTmFtZSI6ImFnZSIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxOSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJjdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJuYW1lIiwiVHlwZSI6eyJUb2tlblR5cGUiOjE1LCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsImN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiNCI6eyJJZCI6NCwiTmFtZSI6ImNoaWxkIiwiVHlwZSI6eyJUb2tlblR5cGUiOjAsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiY3RyTmFtZSI6IkNoaWxkMiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX19fQ== [meta_e] \ No newline at end of file diff --git a/testing/schemas/uint.benc b/testing/schemas/uint.benc deleted file mode 100644 index 733ebd0..0000000 --- a/testing/schemas/uint.benc +++ /dev/null @@ -1,14 +0,0 @@ -header unsignedInt; - -ctr UintTest { - uint64 ui64 = 1; - []uint64 ui64Arr = 2; - ui64Map = 3; - - uint32 ui32 = 4; - uint16 ui16 = 5; - uint ui = 7; -} - -# DO NOT EDIT. -# [meta_s] eyJtc2dzIjp7IlVpbnRUZXN0Ijp7InJJZHMiOm51bGwsImZpZWxkcyI6eyIxIjp7IklkIjoxLCJOYW1lIjoidWk2NCIsIlR5cGUiOnsiVG9rZW5UeXBlIjoxMCwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfX0sIjIiOnsiSWQiOjIsIk5hbWUiOiJ1aTY0QXJyIiwiVHlwZSI6eyJUb2tlblR5cGUiOjAsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6eyJUb2tlblR5cGUiOjEwLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9LCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5Ijp0cnVlLCJJc01hcCI6ZmFsc2V9fSwiMyI6eyJJZCI6MywiTmFtZSI6InVpNjRNYXAiLCJUeXBlIjp7IlRva2VuVHlwZSI6MCwiTWFwS2V5VHlwZSI6eyJUb2tlblR5cGUiOjEwLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9LCJDaGlsZFR5cGUiOnsiVG9rZW5UeXBlIjoxMSwiTWFwS2V5VHlwZSI6bnVsbCwiQ2hpbGRUeXBlIjpudWxsLCJDdHJOYW1lIjoiIiwiSXNVbnNhZmUiOmZhbHNlLCJJc0FycmF5IjpmYWxzZSwiSXNNYXAiOmZhbHNlfSwiQ3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjp0cnVlfX0sIjQiOnsiSWQiOjQsIk5hbWUiOiJ1aTMyIiwiVHlwZSI6eyJUb2tlblR5cGUiOjExLCJNYXBLZXlUeXBlIjpudWxsLCJDaGlsZFR5cGUiOm51bGwsIkN0ck5hbWUiOiIiLCJJc1Vuc2FmZSI6ZmFsc2UsIklzQXJyYXkiOmZhbHNlLCJJc01hcCI6ZmFsc2V9fSwiNSI6eyJJZCI6NSwiTmFtZSI6InVpMTYiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTIsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiQ3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19LCI3Ijp7IklkIjo3LCJOYW1lIjoidWkiLCJUeXBlIjp7IlRva2VuVHlwZSI6MTMsIk1hcEtleVR5cGUiOm51bGwsIkNoaWxkVHlwZSI6bnVsbCwiQ3RyTmFtZSI6IiIsIklzVW5zYWZlIjpmYWxzZSwiSXNBcnJheSI6ZmFsc2UsIklzTWFwIjpmYWxzZX19fX19fQ== [meta_e] \ No newline at end of file diff --git a/testing/unsignedInt/uint_test.go b/testing/unsignedInt/uint_test.go deleted file mode 100644 index 0a4a006..0000000 --- a/testing/unsignedInt/uint_test.go +++ /dev/null @@ -1,204 +0,0 @@ -// Code generated by bencgen golang. DO NOT EDIT. -// source: ../schemas/uint.benc - -package unsignedInt - -import ( - "github.com/deneonet/benc/std" - "github.com/deneonet/benc/impl/gen" -) - -// Struct - UintTest -type UintTest struct { - Ui64 uint64 - Ui64Arr []uint64 - Ui64Map map[uint64]uint32 - Ui32 uint32 - Ui16 uint16 - Ui uint -} - -// Reserved Ids - UintTest -var uintTestRIds = []uint16{} - -// Size - UintTest -func (uintTest *UintTest) Size() int { - return uintTest.size(0) -} - -// Nested Size - UintTest -func (uintTest *UintTest) size(id uint16) (s int) { - s += bstd.SizeUint64() + 2 - s += bstd.SizeSlice(uintTest.Ui64Arr, bstd.SizeUint64) + 2 - s += bstd.SizeMap(uintTest.Ui64Map, bstd.SizeUint64, bstd.SizeUint32) + 2 - s += bstd.SizeUint32() + 2 - s += bstd.SizeUint16() + 2 - s += bstd.SizeUint(uintTest.Ui) + 2 - - if id > 255 { - s += 5 - return - } - s += 4 - return -} - -// SizePlain - UintTest -func (uintTest *UintTest) SizePlain() (s int) { - s += bstd.SizeUint64() - s += bstd.SizeSlice(uintTest.Ui64Arr, bstd.SizeUint64) - s += bstd.SizeMap(uintTest.Ui64Map, bstd.SizeUint64, bstd.SizeUint32) - s += bstd.SizeUint32() - s += bstd.SizeUint16() - s += bstd.SizeUint(uintTest.Ui) - return -} - -// Marshal - UintTest -func (uintTest *UintTest) Marshal(b []byte) { - uintTest.marshal(0, b, 0) -} - -// Nested Marshal - UintTest -func (uintTest *UintTest) marshal(tn int, b []byte, id uint16) (n int) { - n = bgenimpl.MarshalTag(tn, b, bgenimpl.Container, id) - n = bgenimpl.MarshalTag(n, b, bgenimpl.Fixed64, 1) - n = bstd.MarshalUint64(n, b, uintTest.Ui64) - n = bgenimpl.MarshalTag(n, b, bgenimpl.ArrayMap, 2) - n = bstd.MarshalSlice(n, b, uintTest.Ui64Arr, bstd.MarshalUint64) - n = bgenimpl.MarshalTag(n, b, bgenimpl.ArrayMap, 3) - n = bstd.MarshalMap(n, b, uintTest.Ui64Map, bstd.MarshalUint64, bstd.MarshalUint32) - n = bgenimpl.MarshalTag(n, b, bgenimpl.Fixed32, 4) - n = bstd.MarshalUint32(n, b, uintTest.Ui32) - n = bgenimpl.MarshalTag(n, b, bgenimpl.Fixed16, 5) - n = bstd.MarshalUint16(n, b, uintTest.Ui16) - n = bgenimpl.MarshalTag(n, b, bgenimpl.Varint, 7) - n = bstd.MarshalUint(n, b, uintTest.Ui) - - n += 2 - b[n-2] = 1 - b[n-1] = 1 - return -} - -// MarshalPlain - UintTest -func (uintTest *UintTest) MarshalPlain(tn int, b []byte) (n int) { - n = tn - n = bstd.MarshalUint64(n, b, uintTest.Ui64) - n = bstd.MarshalSlice(n, b, uintTest.Ui64Arr, bstd.MarshalUint64) - n = bstd.MarshalMap(n, b, uintTest.Ui64Map, bstd.MarshalUint64, bstd.MarshalUint32) - n = bstd.MarshalUint32(n, b, uintTest.Ui32) - n = bstd.MarshalUint16(n, b, uintTest.Ui16) - n = bstd.MarshalUint(n, b, uintTest.Ui) - return n -} - -// Unmarshal - UintTest -func (uintTest *UintTest) Unmarshal(b []byte) (err error) { - _, err = uintTest.unmarshal(0, b, []uint16{}, 0) - return -} - -// Nested Unmarshal - UintTest -func (uintTest *UintTest) unmarshal(tn int, b []byte, r []uint16, id uint16) (n int, err error) { - var ok bool - if n, ok, err = bgenimpl.HandleCompatibility(tn, b, r, id); !ok { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if n, ok, err = bgenimpl.HandleCompatibility(n, b, uintTestRIds, 1); err != nil { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if ok { - if n, uintTest.Ui64, err = bstd.UnmarshalUint64(n, b); err != nil { - return - } - } - if n, ok, err = bgenimpl.HandleCompatibility(n, b, uintTestRIds, 2); err != nil { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if ok { - if n, uintTest.Ui64Arr, err = bstd.UnmarshalSlice[uint64](n, b, bstd.UnmarshalUint64); err != nil { - return - } - } - if n, ok, err = bgenimpl.HandleCompatibility(n, b, uintTestRIds, 3); err != nil { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if ok { - if n, uintTest.Ui64Map, err = bstd.UnmarshalMap[uint64, uint32](n, b, bstd.UnmarshalUint64, bstd.UnmarshalUint32); err != nil { - return - } - } - if n, ok, err = bgenimpl.HandleCompatibility(n, b, uintTestRIds, 4); err != nil { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if ok { - if n, uintTest.Ui32, err = bstd.UnmarshalUint32(n, b); err != nil { - return - } - } - if n, ok, err = bgenimpl.HandleCompatibility(n, b, uintTestRIds, 5); err != nil { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if ok { - if n, uintTest.Ui16, err = bstd.UnmarshalUint16(n, b); err != nil { - return - } - } - if n, ok, err = bgenimpl.HandleCompatibility(n, b, uintTestRIds, 7); err != nil { - if err == bgenimpl.ErrEof { - return n, nil - } - return - } - if ok { - if n, uintTest.Ui, err = bstd.UnmarshalUint(n, b); err != nil { - return - } - } - n += 2 - return -} - -// UnmarshalPlain - UintTest -func (uintTest *UintTest) UnmarshalPlain(tn int, b []byte) (n int, err error) { - n = tn - if n, uintTest.Ui64, err = bstd.UnmarshalUint64(n, b); err != nil { - return - } - if n, uintTest.Ui64Arr, err = bstd.UnmarshalSlice[uint64](n, b, bstd.UnmarshalUint64); err != nil { - return - } - if n, uintTest.Ui64Map, err = bstd.UnmarshalMap[uint64, uint32](n, b, bstd.UnmarshalUint64, bstd.UnmarshalUint32); err != nil { - return - } - if n, uintTest.Ui32, err = bstd.UnmarshalUint32(n, b); err != nil { - return - } - if n, uintTest.Ui16, err = bstd.UnmarshalUint16(n, b); err != nil { - return - } - if n, uintTest.Ui, err = bstd.UnmarshalUint(n, b); err != nil { - return - } - return -} -