From 6fafe0eb33849f895f58477a093af94642068ac4 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:07:12 -0400 Subject: [PATCH 01/31] chore(cmd/gnoland): disable --flag-config-path (#2991) Not sure about this one. Is anyone using it? Signed-off-by: moul <94029+moul@users.noreply.github.com> Co-authored-by: Morgan --- gno.land/cmd/gnoland/root.go | 10 +--------- gno.land/cmd/gnoland/start.go | 8 -------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/gno.land/cmd/gnoland/root.go b/gno.land/cmd/gnoland/root.go index 8df716b1fed0..b40a1160b0b8 100644 --- a/gno.land/cmd/gnoland/root.go +++ b/gno.land/cmd/gnoland/root.go @@ -5,12 +5,8 @@ import ( "os" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/peterbourgon/ff/v3" - "github.com/peterbourgon/ff/v3/fftoml" ) -const flagConfigFlag = "flag-config-path" - func main() { cmd := newRootCmd(commands.NewDefaultIO()) @@ -21,11 +17,7 @@ func newRootCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ ShortUsage: " [flags] [...]", - ShortHelp: "starts the gnoland blockchain node", - Options: []ff.Option{ - ff.WithConfigFileFlag(flagConfigFlag), - ff.WithConfigFileParser(fftoml.Parser), - }, + ShortHelp: "manages the gnoland blockchain node", }, commands.NewEmptyConfig(), commands.HelpExec, diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index d871cb65aa10..8d1ee81295f5 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -51,7 +51,6 @@ type startCfg struct { genesisFile string chainID string dataDir string - config string lazyInit bool logLevel string @@ -136,13 +135,6 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { "replacement for '%%REMOTE%%' in genesis", ) - fs.StringVar( - &c.config, - flagConfigFlag, - "", - "the flag config file (optional)", - ) - fs.StringVar( &c.logLevel, "log-level", From 464c7f114bf22d2b6b3632b3140f7554f34d4427 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Villaquiran Date: Mon, 21 Oct 2024 17:07:38 +0200 Subject: [PATCH 02/31] feat(cmd/gno): lint all files in folder before panicking (#2202) This Pull request intents to follow up on #2011. As said on that Pull request, currently we show all lint errors on the first analyzed file. If in a folder we have `a.gno` & `b.gno` both with lint errors. `gno lint | run | test` will only find the errors related to one of those files. **This PR aims to show all the lint errors present on the current folder**. Changes: for lint & test cmd: - we modified ParseMemPackage function on gnovm/pkg/gnoland/nodes.go. Before this function returned as soon as an error was found while Parsing the gno file. So we introduced an error slice to keep track of all Parse errors. After parsing all the files we panic with the list of errors only if this list is not empty. - we did the same on parseMemPackageTests function - create a function printRuntimeError that handles the print of the errors inside `catchRuntimeError` function. We did this change in order to be able to recursively call the funtion and handle the case of an []error type composed of scanner.ErrorList errors. ### Results * running on gnovm/tests/integ/several-files-multiple/errors LINT (before): ```sh several-files-multiple-errors % gno lint . file2.gno:3: expected 'IDENT', found '{' (code=2). file2.gno:5: expected type, found '}' (code=2). ``` LINT (after): ```sh gno lint . file2.gno:3: expected 'IDENT', found '{' (code=2). file2.gno:5: expected type, found '}' (code=2). main.gno:5: expected ';', found example (code=2). main.gno:6: expected '}', found 'EOF' (code=2). exit status 1 ```
Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
--- gnovm/cmd/gno/lint.go | 17 ++++++++++++----- gnovm/cmd/gno/lint_test.go | 4 ++++ gnovm/cmd/gno/run_test.go | 5 +++++ gnovm/cmd/gno/test.go | 7 ++++++- gnovm/pkg/gnolang/nodes.go | 8 +++++++- .../several-files-multiple-errors/file2.gno | 5 +++++ .../integ/several-files-multiple-errors/gno.mod | 1 + .../several-files-multiple-errors/main.gno | 6 ++++++ 8 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 gnovm/tests/integ/several-files-multiple-errors/file2.gno create mode 100644 gnovm/tests/integ/several-files-multiple-errors/gno.mod create mode 100644 gnovm/tests/integ/several-files-multiple-errors/main.gno diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 6c497c7e2c06..c6008117f13a 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -17,6 +17,7 @@ import ( "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" osm "github.com/gnolang/gno/tm2/pkg/os" + "go.uber.org/multierr" ) type lintCfg struct { @@ -174,12 +175,18 @@ func catchRuntimeError(pkgPath string, stderr io.WriteCloser, action func()) (ha case *gno.PreprocessError: err := verr.Unwrap() fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") - case scanner.ErrorList: - for _, err := range verr { - fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") - } case error: - fmt.Fprint(stderr, issueFromError(pkgPath, verr).String()+"\n") + errors := multierr.Errors(verr) + for _, err := range errors { + errList, ok := err.(scanner.ErrorList) + if ok { + for _, errorInList := range errList { + fmt.Fprint(stderr, issueFromError(pkgPath, errorInList).String()+"\n") + } + } else { + fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") + } + } case string: fmt.Fprint(stderr, issueFromError(pkgPath, errors.New(verr)).String()+"\n") default: diff --git a/gnovm/cmd/gno/lint_test.go b/gnovm/cmd/gno/lint_test.go index a5c0319cd000..20d21c05d059 100644 --- a/gnovm/cmd/gno/lint_test.go +++ b/gnovm/cmd/gno/lint_test.go @@ -23,6 +23,10 @@ func TestLintApp(t *testing.T) { args: []string{"lint", "../../tests/integ/several-lint-errors/main.gno"}, stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-lint-errors/main.gno:6", errShouldBe: "exit code: 1", + }, { + args: []string{"lint", "../../tests/integ/several-files-multiple-errors/main.gno"}, + stderrShouldContain: "../../tests/integ/several-files-multiple-errors/file2.gno:3: expected 'IDENT', found '{' (code=2).\n../../tests/integ/several-files-multiple-errors/file2.gno:5: expected type, found '}' (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:6: expected '}', found 'EOF' (code=2).\n", + errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/run_main/"}, stderrShouldContain: "./../../tests/integ/run_main: missing 'gno.mod' file (code=1).", diff --git a/gnovm/cmd/gno/run_test.go b/gnovm/cmd/gno/run_test.go index 975868b7daf2..e5aa1bd62792 100644 --- a/gnovm/cmd/gno/run_test.go +++ b/gnovm/cmd/gno/run_test.go @@ -83,6 +83,11 @@ func TestRunApp(t *testing.T) { args: []string{"run", "-expr", "Context()", "../../tests/integ/context/context.gno"}, stdoutShouldContain: "Context worked", }, + { + args: []string{"run", "../../tests/integ/several-files-multiple-errors/"}, + stderrShouldContain: "../../tests/integ/several-files-multiple-errors/file2.gno:3: expected 'IDENT', found '{' (code=2).\n../../tests/integ/several-files-multiple-errors/file2.gno:5: expected type, found '}' (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:6: expected '}', found 'EOF' (code=2).", + errShouldBe: "exit code: 1", + }, // TODO: a test file // TODO: args // TODO: nativeLibs VS stdlibs diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 5884463a5528..af7fa28a14dc 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -577,6 +577,7 @@ func loadTestFuncs(pkgName string, t *testFuncs, tfiles *gno.FileSet) *testFuncs func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { tset = &gno.FileSet{} itset = &gno.FileSet{} + var errs error for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // skip this file. @@ -586,7 +587,8 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { } n, err := gno.ParseFile(mfile.Name, mfile.Body) if err != nil { - panic(err) + errs = multierr.Append(errs, err) + continue } if n == nil { panic("should not happen") @@ -606,6 +608,9 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { memPkg.Name, memPkg.Name, n.PkgName, mfile)) } } + if errs != nil { + panic(errs) + } return tset, itset } diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 5f5e8bd30b98..f1bd78ee646b 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -14,6 +14,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/std" + "go.uber.org/multierr" ) // ---------------------------------------- @@ -1189,6 +1190,7 @@ func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { // or [ParseFile] returns an error, ParseMemPackage panics. func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { fset = &FileSet{} + var errs error for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") || endsWith(mfile.Name, []string{"_test.gno", "_filetest.gno"}) { @@ -1196,7 +1198,8 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { } n, err := ParseFile(mfile.Name, mfile.Body) if err != nil { - panic(err) + errs = multierr.Append(errs, err) + continue } if memPkg.Name != string(n.PkgName) { panic(fmt.Sprintf( @@ -1206,6 +1209,9 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { // add package file. fset.AddFiles(n) } + if errs != nil { + panic(errs) + } return fset } diff --git a/gnovm/tests/integ/several-files-multiple-errors/file2.gno b/gnovm/tests/integ/several-files-multiple-errors/file2.gno new file mode 100644 index 000000000000..39ec59973ef8 --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/file2.gno @@ -0,0 +1,5 @@ +package main + +type{ + +} \ No newline at end of file diff --git a/gnovm/tests/integ/several-files-multiple-errors/gno.mod b/gnovm/tests/integ/several-files-multiple-errors/gno.mod new file mode 100644 index 000000000000..88485411822c --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/gno.mod @@ -0,0 +1 @@ +module gno.land/tests/severalerrors \ No newline at end of file diff --git a/gnovm/tests/integ/several-files-multiple-errors/main.gno b/gnovm/tests/integ/several-files-multiple-errors/main.gno new file mode 100644 index 000000000000..f29aa7ecd33a --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/main.gno @@ -0,0 +1,6 @@ +package main + +func main() { + for { + _ example +} \ No newline at end of file From a5c1d186216a193e9b013226820eda02a93e22a1 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Mon, 21 Oct 2024 17:10:55 +0200 Subject: [PATCH 03/31] fix(tm2): avoid mutex copy in marshal and unmarshal methods (#2981) Avoid copying of Mutex at several places. Add missing lock / unlock calls. Improve test coverage for protobuf timestamp and duration. `go vet` doesn't complain anymore on Mutex copy. Addresses #2954.
Contributors' checklist... - [*] Added new tests, or not needed, or not feasible - [*] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [*] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [*] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests
--- tm2/pkg/amino/amino.go | 2 +- tm2/pkg/amino/json_test.go | 29 ++++++++++++++++++++++++++++- tm2/pkg/amino/wellknown.go | 23 +++++++++++++++-------- tm2/pkg/bitarray/bit_array.go | 12 +++++++++++- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/tm2/pkg/amino/amino.go b/tm2/pkg/amino/amino.go index ecff955a5822..e402c74f4fdc 100644 --- a/tm2/pkg/amino/amino.go +++ b/tm2/pkg/amino/amino.go @@ -760,7 +760,7 @@ func (cdc *Codec) MarshalJSON(o interface{}) ([]byte, error) { cdc.doAutoseal() rv := reflect.ValueOf(o) - if rv.Kind() == reflect.Invalid { + if !rv.IsValid() { return []byte("null"), nil } rt := rv.Type() diff --git a/tm2/pkg/amino/json_test.go b/tm2/pkg/amino/json_test.go index e3f7d413fcb9..9b5cd9cff094 100644 --- a/tm2/pkg/amino/json_test.go +++ b/tm2/pkg/amino/json_test.go @@ -12,8 +12,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" - amino "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/amino/pkg" ) @@ -158,6 +160,31 @@ func TestMarshalJSONTime(t *testing.T) { assert.Equal(t, s, s2) } +func TestMarshalJSONPBTime(t *testing.T) { + t.Parallel() + + cdc := amino.NewCodec() + registerTransports(cdc) + + type SimpleStruct struct { + Timestamp *timestamppb.Timestamp + Duration *durationpb.Duration + } + + s := SimpleStruct{ + Timestamp: ×tamppb.Timestamp{Seconds: 1296012345, Nanos: 940483}, + Duration: &durationpb.Duration{Seconds: 100}, + } + + b, err := cdc.MarshalJSON(s) + assert.Nil(t, err) + + var s2 SimpleStruct + err = cdc.UnmarshalJSON(b, &s2) + assert.Nil(t, err) + assert.Equal(t, s, s2) +} + type fp struct { Name string Version int diff --git a/tm2/pkg/amino/wellknown.go b/tm2/pkg/amino/wellknown.go index 9dbafcbecec0..7720c2894d91 100644 --- a/tm2/pkg/amino/wellknown.go +++ b/tm2/pkg/amino/wellknown.go @@ -237,16 +237,21 @@ func encodeReflectJSONWellKnown(w io.Writer, info *TypeInfo, rv reflect.Value, f } return true, nil // Google "well known" types. + // The protobuf Timestamp and Duration values contain a Mutex, and therefore must not be copied. + // The corresponding reflect value may not be addressable, we can not safely get their pointer. + // So we just extract the `Seconds` and `Nanos` fields from the reflect value, without copying + // the whole struct, and encode them as their coresponding time.Time or time.Duration value. case gTimestampType: - t := rv.Interface().(timestamppb.Timestamp) - err = EncodeJSONPBTimestamp(w, t) + t := time.Unix(rv.Interface().(timestamppb.Timestamp).Seconds, int64(rv.Interface().(timestamppb.Timestamp).Nanos)) + err = EncodeJSONTime(w, t) if err != nil { return false, err } return true, nil case gDurationType: - d := rv.Interface().(durationpb.Duration) - err = EncodeJSONPBDuration(w, d) + d := time.Duration(rv.Interface().(durationpb.Duration).Seconds) * time.Second + d += time.Duration(rv.Interface().(durationpb.Duration).Nanos) + err = EncodeJSONDuration(w, d) if err != nil { return false, err } @@ -300,7 +305,8 @@ func decodeReflectJSONWellKnown(bz []byte, info *TypeInfo, rv reflect.Value, fop if err != nil { return false, err } - rv.Set(reflect.ValueOf(t)) + rv.FieldByName("Seconds").Set(reflect.ValueOf(t.Seconds)) + rv.FieldByName("Nanos").Set(reflect.ValueOf(t.Nanos)) return true, nil case gDurationType: var d durationpb.Duration @@ -308,7 +314,8 @@ func decodeReflectJSONWellKnown(bz []byte, info *TypeInfo, rv reflect.Value, fop if err != nil { return false, err } - rv.Set(reflect.ValueOf(d)) + rv.FieldByName("Seconds").Set(reflect.ValueOf(d.Seconds)) + rv.FieldByName("Nanos").Set(reflect.ValueOf(d.Nanos)) return true, nil // TODO: port each below to above without proto dependency // for unmarshaling code, to minimize dependencies. @@ -426,7 +433,7 @@ func EncodeJSONTime(w io.Writer, t time.Time) (err error) { return EncodeJSONTimeValue(w, t.Unix(), int32(t.Nanosecond())) } -func EncodeJSONPBTimestamp(w io.Writer, t timestamppb.Timestamp) (err error) { +func EncodeJSONPBTimestamp(w io.Writer, t *timestamppb.Timestamp) (err error) { return EncodeJSONTimeValue(w, t.GetSeconds(), t.GetNanos()) } @@ -456,7 +463,7 @@ func EncodeJSONDuration(w io.Writer, d time.Duration) (err error) { return EncodeJSONDurationValue(w, int64(d)/1e9, int32(int64(d)%1e9)) } -func EncodeJSONPBDuration(w io.Writer, d durationpb.Duration) (err error) { +func EncodeJSONPBDuration(w io.Writer, d *durationpb.Duration) (err error) { return EncodeJSONDurationValue(w, d.GetSeconds(), d.GetNanos()) } diff --git a/tm2/pkg/bitarray/bit_array.go b/tm2/pkg/bitarray/bit_array.go index 2f7b184b9389..a48c71a56503 100644 --- a/tm2/pkg/bitarray/bit_array.go +++ b/tm2/pkg/bitarray/bit_array.go @@ -394,8 +394,12 @@ func (bA *BitArray) UnmarshalJSON(bz []byte) error { if b == "null" { // This is required e.g. for encoding/json when decoding // into a pointer with pre-allocated BitArray. + bA.mtx.Lock() + defer bA.mtx.Unlock() + bA.Bits = 0 bA.Elems = nil + return nil } @@ -414,6 +418,12 @@ func (bA *BitArray) UnmarshalJSON(bz []byte) error { bA2.SetIndex(i, true) } } - *bA = *bA2 //nolint:govet + + bA.mtx.Lock() + defer bA.mtx.Unlock() + + bA.Bits = bA2.Bits + bA.Elems = bA2.Elems + return nil } From 13dfd218a040afe1675a5f7e8942e3042ace9d3e Mon Sep 17 00:00:00 2001 From: Leon Hudak <33522493+leohhhn@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:12:29 +0200 Subject: [PATCH 04/31] chore(pages): update bounty Terms & Conditions link (#2982) ## Description By internal request.
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests
--- examples/gno.land/r/gnoland/pages/page_contribute.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/gnoland/pages/page_contribute.gno b/examples/gno.land/r/gnoland/pages/page_contribute.gno index a4bdfabb6ef2..0855dc327cd2 100644 --- a/examples/gno.land/r/gnoland/pages/page_contribute.gno +++ b/examples/gno.land/r/gnoland/pages/page_contribute.gno @@ -45,7 +45,7 @@ Don't fear your work being "stolen": if a submission is the result of multiple p - If you, for instance, cannot complete the entirety of the task or, as a non-developer, can only contribute a part of the specification/implementation, you may still be awarded a bounty for your input in the contribution. - If Alice makes a PR that aside from implementing what's required, also undertakes creating useful tools among the way, she may qualify for an "outstanding contribution"; and may be awarded up to 25% more of the original bounty's value. Or she may also ask if the team would be willing to offer a different bounty for the implementation of the tools. -Participants in the gno.land Bounty Program must meet the legal Terms and Conditions referenced [here](https://docs.google.com/document/d/1aXrZ6japdAykB5FLmHCCeBZTo-2tbZQHSQi79ITaTK0). +Participants in the gno.land Bounty Program must meet the legal Terms and Conditions referenced [here](https://docs.google.com/document/d/e/2PACX-1vSUF-JwIXGscrNsc5QBD7Pa6i83mXUGogAEIf1wkeb_w42UgL3Lj6jFKMlNTdwEMUnhsLkjRlhe25K4/pub). ### Bounty sizes From 88a0c4e41d6ecc011261b94a8293dfdb9a52072e Mon Sep 17 00:00:00 2001 From: 6h057 <15034695+omarsy@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:14:57 +0200 Subject: [PATCH 05/31] fix(gonative): add constant information when we define a go native value (#2848) First part of the fix: https://github.com/gnolang/gno/issues/2836 The second part is addressed here: https://github.com/gnolang/gno/pull/2731 --- gnovm/pkg/gnolang/gonative.go | 15 ++++-- gnovm/pkg/gnolang/preprocess.go | 4 ++ gnovm/pkg/gnolang/preprocess_test.go | 8 ++-- gnovm/tests/files/assign29_native.gno | 14 ++++++ gnovm/tests/imports.go | 67 +++++++++++++-------------- 5 files changed, 67 insertions(+), 41 deletions(-) create mode 100644 gnovm/tests/files/assign29_native.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 0676854aa39f..fe92f5bcd235 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -1258,16 +1258,25 @@ func (x *PackageNode) DefineGoNativeType(rt reflect.Type) { x.Define(Name(name), asValue(nt)) } -func (x *PackageNode) DefineGoNativeValue(n Name, nv interface{}) { +func (x *PackageNode) DefineGoNativeValue(name Name, nv interface{}) { + x.defineGoNativeValue(false, name, nv) +} + +func (x *PackageNode) DefineGoNativeConstValue(name Name, nv interface{}) { + x.defineGoNativeValue(true, name, nv) +} + +func (x *PackageNode) defineGoNativeValue(isConst bool, n Name, nv interface{}) { if debug { - debug.Printf("*PackageNode.DefineGoNativeValue(%s)\n", reflect.ValueOf(nv).String()) + debug.Printf("*PackageNode.defineGoNativeValue(%s)\n", reflect.ValueOf(nv).String()) } rv := reflect.ValueOf(nv) // rv is not settable, so create something that is. rt := rv.Type() rv2 := reflect.New(rt).Elem() rv2.Set(rv) - x.Define(n, go2GnoValue(nilAllocator, rv2)) + tv := go2GnoValue(nilAllocator, rv2) + x.Define2(isConst, n, tv.T, tv) } // ---------------------------------------- diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 61096626f283..757cbbae3170 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2093,6 +2093,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) + if nt, ok := lt.(*NativeType); ok && nt.Kind() == FuncKind { + panic(fmt.Sprintf("cannot assign to %s (neither addressable nor a map index expression)", lx)) + } + // if lt is interface, nothing will happen checkOrConvertType(store, last, &n.Rhs[i], lt, true) } diff --git a/gnovm/pkg/gnolang/preprocess_test.go b/gnovm/pkg/gnolang/preprocess_test.go index 73e1318b0626..53ad97dd9723 100644 --- a/gnovm/pkg/gnolang/preprocess_test.go +++ b/gnovm/pkg/gnolang/preprocess_test.go @@ -11,8 +11,8 @@ import ( func TestPreprocess_BinaryExpressionOneNative(t *testing.T) { pn := NewPackageNode("time", "time", nil) - pn.DefineGoNativeValue("Millisecond", time.Millisecond) - pn.DefineGoNativeValue("Second", time.Second) + pn.DefineGoNativeConstValue("Millisecond", time.Millisecond) + pn.DefineGoNativeConstValue("Second", time.Second) pn.DefineGoNativeType(reflect.TypeOf(time.Duration(0))) pv := pn.NewPackage() store := gonativeTestStore(pn, pv) @@ -37,8 +37,8 @@ func main() { func TestPreprocess_BinaryExpressionBothNative(t *testing.T) { pn := NewPackageNode("time", "time", nil) - pn.DefineGoNativeValue("March", time.March) - pn.DefineGoNativeValue("Wednesday", time.Wednesday) + pn.DefineGoNativeConstValue("March", time.March) + pn.DefineGoNativeConstValue("Wednesday", time.Wednesday) pn.DefineGoNativeType(reflect.TypeOf(time.Month(0))) pn.DefineGoNativeType(reflect.TypeOf(time.Weekday(0))) pv := pn.NewPackage() diff --git a/gnovm/tests/files/assign29_native.gno b/gnovm/tests/files/assign29_native.gno new file mode 100644 index 000000000000..a404f703fc12 --- /dev/null +++ b/gnovm/tests/files/assign29_native.gno @@ -0,0 +1,14 @@ +package main + +import ( + "time" +) + +func main() { + time.Now = func() time.Time { + return time.Time{} + } +} + +// Error: +// main/files/assign29_native.gno:8:2: cannot assign to time.Now (neither addressable nor a map index expression) diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index b8532253ce3f..66398ba5f50c 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -222,23 +222,23 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri return pkg, pkg.NewPackage() case "time": pkg := gno.NewPackageNode("time", pkgPath, nil) - pkg.DefineGoNativeValue("Millisecond", time.Millisecond) - pkg.DefineGoNativeValue("Second", time.Second) - pkg.DefineGoNativeValue("Minute", time.Minute) - pkg.DefineGoNativeValue("Hour", time.Hour) - pkg.DefineGoNativeValue("Date", time.Date) - pkg.DefineGoNativeValue("Now", func() time.Time { return time.Unix(0, 0).UTC() }) // deterministic - pkg.DefineGoNativeValue("January", time.January) - pkg.DefineGoNativeValue("February", time.February) - pkg.DefineGoNativeValue("March", time.March) - pkg.DefineGoNativeValue("April", time.April) - pkg.DefineGoNativeValue("May", time.May) - pkg.DefineGoNativeValue("June", time.June) - pkg.DefineGoNativeValue("July", time.July) - pkg.DefineGoNativeValue("August", time.August) - pkg.DefineGoNativeValue("September", time.September) - pkg.DefineGoNativeValue("November", time.November) - pkg.DefineGoNativeValue("December", time.December) + pkg.DefineGoNativeConstValue("Millisecond", time.Millisecond) + pkg.DefineGoNativeConstValue("Second", time.Second) + pkg.DefineGoNativeConstValue("Minute", time.Minute) + pkg.DefineGoNativeConstValue("Hour", time.Hour) + pkg.DefineGoNativeConstValue("Date", time.Date) + pkg.DefineGoNativeConstValue("Now", func() time.Time { return time.Unix(0, 0).UTC() }) // deterministic + pkg.DefineGoNativeConstValue("January", time.January) + pkg.DefineGoNativeConstValue("February", time.February) + pkg.DefineGoNativeConstValue("March", time.March) + pkg.DefineGoNativeConstValue("April", time.April) + pkg.DefineGoNativeConstValue("May", time.May) + pkg.DefineGoNativeConstValue("June", time.June) + pkg.DefineGoNativeConstValue("July", time.July) + pkg.DefineGoNativeConstValue("August", time.August) + pkg.DefineGoNativeConstValue("September", time.September) + pkg.DefineGoNativeConstValue("November", time.November) + pkg.DefineGoNativeConstValue("December", time.December) pkg.DefineGoNativeValue("UTC", time.UTC) pkg.DefineGoNativeValue("Unix", time.Unix) pkg.DefineGoNativeType(reflect.TypeOf(time.Time{})) @@ -272,21 +272,20 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg := gno.NewPackageNode("math", pkgPath, nil) pkg.DefineGoNativeValue("Abs", math.Abs) pkg.DefineGoNativeValue("Cos", math.Cos) - pkg.DefineGoNativeValue("Pi", math.Pi) + pkg.DefineGoNativeConstValue("Pi", math.Pi) pkg.DefineGoNativeValue("Float64bits", math.Float64bits) - pkg.DefineGoNativeValue("Pi", math.Pi) - pkg.DefineGoNativeValue("MaxFloat32", math.MaxFloat32) - pkg.DefineGoNativeValue("MaxFloat64", math.MaxFloat64) - pkg.DefineGoNativeValue("MaxUint32", uint32(math.MaxUint32)) - pkg.DefineGoNativeValue("MaxUint64", uint64(math.MaxUint64)) - pkg.DefineGoNativeValue("MinInt8", math.MinInt8) - pkg.DefineGoNativeValue("MinInt16", math.MinInt16) - pkg.DefineGoNativeValue("MinInt32", math.MinInt32) - pkg.DefineGoNativeValue("MinInt64", int64(math.MinInt64)) - pkg.DefineGoNativeValue("MaxInt8", math.MaxInt8) - pkg.DefineGoNativeValue("MaxInt16", math.MaxInt16) - pkg.DefineGoNativeValue("MaxInt32", math.MaxInt32) - pkg.DefineGoNativeValue("MaxInt64", int64(math.MaxInt64)) + pkg.DefineGoNativeConstValue("MaxFloat32", math.MaxFloat32) + pkg.DefineGoNativeConstValue("MaxFloat64", math.MaxFloat64) + pkg.DefineGoNativeConstValue("MaxUint32", uint32(math.MaxUint32)) + pkg.DefineGoNativeConstValue("MaxUint64", uint64(math.MaxUint64)) + pkg.DefineGoNativeConstValue("MinInt8", math.MinInt8) + pkg.DefineGoNativeConstValue("MinInt16", math.MinInt16) + pkg.DefineGoNativeConstValue("MinInt32", math.MinInt32) + pkg.DefineGoNativeConstValue("MinInt64", int64(math.MinInt64)) + pkg.DefineGoNativeConstValue("MaxInt8", math.MaxInt8) + pkg.DefineGoNativeConstValue("MaxInt16", math.MaxInt16) + pkg.DefineGoNativeConstValue("MaxInt32", math.MaxInt32) + pkg.DefineGoNativeConstValue("MaxInt64", int64(math.MaxInt64)) return pkg, pkg.NewPackage() case "math/rand": // XXX only expose for tests. @@ -321,13 +320,13 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri return pkg, pkg.NewPackage() case "compress/flate": pkg := gno.NewPackageNode("flate", pkgPath, nil) - pkg.DefineGoNativeValue("BestSpeed", flate.BestSpeed) + pkg.DefineGoNativeConstValue("BestSpeed", flate.BestSpeed) return pkg, pkg.NewPackage() case "compress/gzip": pkg := gno.NewPackageNode("gzip", pkgPath, nil) pkg.DefineGoNativeType(reflect.TypeOf(gzip.Writer{})) - pkg.DefineGoNativeValue("BestCompression", gzip.BestCompression) - pkg.DefineGoNativeValue("BestSpeed", gzip.BestSpeed) + pkg.DefineGoNativeConstValue("BestCompression", gzip.BestCompression) + pkg.DefineGoNativeConstValue("BestSpeed", gzip.BestSpeed) return pkg, pkg.NewPackage() case "context": pkg := gno.NewPackageNode("context", pkgPath, nil) From af169ffd233caabae746b18c9381c7ad695ebbed Mon Sep 17 00:00:00 2001 From: 6h057 <15034695+omarsy@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:28:16 +0200 Subject: [PATCH 06/31] fix(ghverify): fix avl tree iteration in `Render` and `GetFeedDefinitions` (#2933) This pull request resolves a bug in the iteration logic of the `iterate` function from `gno.land/p/demo/avl` (avlTree) as used in two key areas: the `Render` function of `gno.land/r/gnoland/ghverify` and the `GetFeedDefinitions` function of `gno.land/p/demo/gnorkle/gnorkle`. ### Problem: In both instances, the `iterate` function was returning `true` after processing the first item, which prematurely halted the iteration. As a result, only the first item was processed, and all subsequent items were ignored. --- .../p/demo/gnorkle/gnorkle/instance.gno | 2 +- .../gno.land/r/gnoland/ghverify/contract.gno | 2 +- .../r/gnoland/ghverify/contract_test.gno | 33 +++++++++++-------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno b/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno index 22746d569a81..eea4782909e7 100644 --- a/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno +++ b/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno @@ -227,7 +227,7 @@ func (i *Instance) GetFeedDefinitions(forAddress string) (string, error) { first = false buf.Write(taskBytes) - return true + return false }) if err != nil { diff --git a/examples/gno.land/r/gnoland/ghverify/contract.gno b/examples/gno.land/r/gnoland/ghverify/contract.gno index b40c9ef14486..4f2715b79e7a 100644 --- a/examples/gno.land/r/gnoland/ghverify/contract.gno +++ b/examples/gno.land/r/gnoland/ghverify/contract.gno @@ -139,7 +139,7 @@ func Render(_ string) string { result += `"` + handle + `": "` + address.(string) + `"` appendComma = true - return true + return false }) return result + "}" diff --git a/examples/gno.land/r/gnoland/ghverify/contract_test.gno b/examples/gno.land/r/gnoland/ghverify/contract_test.gno index d9c399942aee..5c0be0afcb1a 100644 --- a/examples/gno.land/r/gnoland/ghverify/contract_test.gno +++ b/examples/gno.land/r/gnoland/ghverify/contract_test.gno @@ -9,7 +9,8 @@ import ( func TestVerificationLifecycle(t *testing.T) { defaultAddress := std.GetOrigCaller() - userAddress := std.Address(testutils.TestAddress("user")) + user1Address := std.Address(testutils.TestAddress("user 1")) + user2Address := std.Address(testutils.TestAddress("user 2")) // Verify request returns no feeds. result := GnorkleEntrypoint("request") @@ -18,7 +19,7 @@ func TestVerificationLifecycle(t *testing.T) { } // Make a verification request with the created user. - std.TestSetOrigCaller(userAddress) + std.TestSetOrigCaller(user1Address) RequestVerification("deelawn") // A subsequent request from the same address should panic because there is @@ -42,26 +43,32 @@ func TestVerificationLifecycle(t *testing.T) { t.Fatalf("expected empty request result, got %s", result) } + // Make a verification request with the created user. + std.TestSetOrigCaller(user2Address) + RequestVerification("omarsy") + // Set the caller back to the whitelisted user and verify that the feed data // returned matches what should have been created by the `RequestVerification` // invocation. std.TestSetOrigCaller(defaultAddress) result = GnorkleEntrypoint("request") - expResult := `[{"id":"` + string(userAddress) + `","type":"0","value_type":"string","tasks":[{"gno_address":"` + - string(userAddress) + `","github_handle":"deelawn"}]}]` + expResult := `[{"id":"` + string(user1Address) + `","type":"0","value_type":"string","tasks":[{"gno_address":"` + + string(user1Address) + `","github_handle":"deelawn"}]},` + + `{"id":"` + string(user2Address) + `","type":"0","value_type":"string","tasks":[{"gno_address":"` + + string(user2Address) + `","github_handle":"omarsy"}]}]` if result != expResult { t.Fatalf("expected request result %s, got %s", expResult, result) } // Try to trigger feed ingestion from the non-authorized user. - std.TestSetOrigCaller(userAddress) + std.TestSetOrigCaller(user1Address) func() { defer func() { if r := recover(); r != nil { errMsg = r.(error).Error() } }() - GnorkleEntrypoint("ingest," + string(userAddress) + ",OK") + GnorkleEntrypoint("ingest," + string(user1Address) + ",OK") }() if errMsg != "caller not whitelisted" { t.Fatalf("expected caller not whitelisted, got %s", errMsg) @@ -69,15 +76,15 @@ func TestVerificationLifecycle(t *testing.T) { // Set the caller back to the whitelisted user and transfer contract ownership. std.TestSetOrigCaller(defaultAddress) - SetOwner(userAddress) + SetOwner(defaultAddress) // Now trigger the feed ingestion from the user and new owner and only whitelisted address. - std.TestSetOrigCaller(userAddress) - GnorkleEntrypoint("ingest," + string(userAddress) + ",OK") + GnorkleEntrypoint("ingest," + string(user1Address) + ",OK") + GnorkleEntrypoint("ingest," + string(user2Address) + ",OK") // Verify the ingestion autocommitted the value and triggered the post handler. data := Render("") - expResult = `{"deelawn": "` + string(userAddress) + `"}` + expResult = `{"deelawn": "` + string(user1Address) + `","omarsy": "` + string(user2Address) + `"}` if data != expResult { t.Fatalf("expected render data %s, got %s", expResult, data) } @@ -89,10 +96,10 @@ func TestVerificationLifecycle(t *testing.T) { } // Check that the accessor functions are working as expected. - if handle := GetHandleByAddress(string(userAddress)); handle != "deelawn" { + if handle := GetHandleByAddress(string(user1Address)); handle != "deelawn" { t.Fatalf("expected deelawn, got %s", handle) } - if address := GetAddressByHandle("deelawn"); address != string(userAddress) { - t.Fatalf("expected %s, got %s", string(userAddress), address) + if address := GetAddressByHandle("deelawn"); address != string(user1Address) { + t.Fatalf("expected %s, got %s", string(user1Address), address) } } From 8417ca436350d983d7310ea11bdd118ee15d15eb Mon Sep 17 00:00:00 2001 From: Morgan Date: Mon, 21 Oct 2024 20:58:59 +0200 Subject: [PATCH 07/31] chore: remove misc/logos (#2965) Unmaintained, and we're going in another direction with gnobro anyway. --- .github/workflows/misc.yml | 1 - misc/logos/README.md | 11 - misc/logos/buffer.go | 355 ------------- misc/logos/cmd/logos.go | 171 ------ misc/logos/image.png | Bin 479803 -> 0 bytes misc/logos/misc.go | 155 ------ misc/logos/misc_test.go | 166 ------ misc/logos/stack.go | 160 ------ misc/logos/types.go | 1006 ------------------------------------ misc/logos/types_test.go | 47 -- misc/logos/unicode.go | 86 --- 11 files changed, 2158 deletions(-) delete mode 100644 misc/logos/README.md delete mode 100644 misc/logos/buffer.go delete mode 100644 misc/logos/cmd/logos.go delete mode 100644 misc/logos/image.png delete mode 100644 misc/logos/misc.go delete mode 100644 misc/logos/misc_test.go delete mode 100644 misc/logos/stack.go delete mode 100644 misc/logos/types.go delete mode 100644 misc/logos/types_test.go delete mode 100644 misc/logos/unicode.go diff --git a/.github/workflows/misc.yml b/.github/workflows/misc.yml index b824235ca2bf..859e1429983d 100644 --- a/.github/workflows/misc.yml +++ b/.github/workflows/misc.yml @@ -22,7 +22,6 @@ jobs: - genproto - genstd - goscan - - logos - loop name: Run Main uses: ./.github/workflows/main_template.yml diff --git a/misc/logos/README.md b/misc/logos/README.md deleted file mode 100644 index ba8ac8333a6e..000000000000 --- a/misc/logos/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Logos Browser - -[Logos](/logos) is a Gno object browser. The modern browser as well as the -modern javascript ecosystem is from a security point of view, completely fucked. -The entire paradigm of continuously updating browsers with incrementally added -features is a security nightmare. - -The Logos browser is based on a new model that is vastly simpler than HTML. -The purpose of Logos is to become a fully expressive web API and implementation -standard that does most of what HTML and the World Wide Web originally intended -to do, but without becoming more complex than necessary. diff --git a/misc/logos/buffer.go b/misc/logos/buffer.go deleted file mode 100644 index 81e8d1abc75d..000000000000 --- a/misc/logos/buffer.go +++ /dev/null @@ -1,355 +0,0 @@ -package logos - -import ( - "fmt" - "strings" - - "github.com/gdamore/tcell/v2" -) - -// ---------------------------------------- -// Buffer - -// A Buffer is a buffer area in which to draw. -type Buffer struct { - Size - Cells []Cell -} - -func NewBuffer(sz Size) *Buffer { - return &Buffer{ - Size: sz, - Cells: make([]Cell, sz.Width*sz.Height), - } -} - -func (bb *Buffer) Reset() { - sz := bb.Size - bb.Cells = make([]Cell, sz.Width*sz.Height) -} - -func (bb *Buffer) GetCell(x, y int) *Cell { - if bb.Width <= x { - panic(fmt.Sprintf( - "index x=%d out of bounds, width=%d", - x, bb.Width)) - } - if bb.Height <= y { - panic(fmt.Sprintf( - "index y=%d out of bounds, height=%d", - y, bb.Height)) - } - return &bb.Cells[y*bb.Width+x] -} - -func (bb *Buffer) Sprint() string { - lines := []string{} - for y := 0; y < bb.Height; y++ { - parts := []string{} - for x := 0; x < bb.Width; x++ { - cell := bb.GetCell(x, y) - parts = append(parts, cell.Character) - // NOTE: hacky way to debug. - if true { - attrs := cell.GetAttrs() - flags := attrs.GetAttrFlags() - parts = append(parts, - fmt.Sprintf("%X", flags)) - } - } - line := strings.Join(parts, "") - lines = append(lines, line) - } - return strings.Join(lines, "\n") -} - -func (bb *Buffer) DrawToScreen(s tcell.Screen) { - sw, sh := s.Size() - if bb.Size.Width != sw || bb.Size.Height != sh { - panic("buffer doesn't match screen size") - } - for y := 0; y < sh; y++ { - for x := 0; x < sw; x++ { - cell := bb.GetCell(x, y) - if x == 0 && y == 0 { - // NOTE: to thwart some inexplicable bugs. - s.SetContent(0, 0, tcell.RunePlus, nil, gDefaultSpaceTStyle) - } else { - mainc, combc, tstyle := cell.GetTCellContent() - s.SetContent(x, y, mainc, combc, tstyle) - } - } - } -} - -// ---------------------------------------- -// Cell - -// A terminal character cell. -type Cell struct { - Character string // 1 unicode character, or " ". - Width int - *Style - Attrs - Ref Elem // reference to element -} - -// NOTE: there is a difference in behavior -// from SetValue(...,c2) when c2 has -// attributes not present in c2.Ref, so the -// two are not equivalent. -func (cc *Cell) SetValueFromCell(c2 *Cell) { - cc.SetValue(c2.Character, c2.Width, c2.Style, c2.Ref) - cc.Character = c2.Character - cc.Width = c2.Width - if c2.Style != nil { - cc.Style = c2.Style - } - cc.Attrs.Merge(c2.GetAttrs()) - if c2.Ref != nil { - cc.Ref = c2.Ref - } -} - -func (cc *Cell) SetValue(chs string, w int, st *Style, el Elem) { - cc.Character = chs - cc.Width = w - if st != nil { - cc.Style = st - } - if el != nil { - cc.Attrs.Merge(el.GetAttrs()) - cc.Ref = el - } -} - -func (cc *Cell) Reset() { - *cc = Cell{} -} - -var gDefaultSpaceTStyle = tcell.StyleDefault. - Dim(true). - Background(tcell.ColorGray) - -// This is where a bit of dynamic logic is performed, -// namely where the attr is used to derive the final style. -func (cc *Cell) GetTCellContent() (mainc rune, combc []rune, tstyle tcell.Style) { - style := cc.Style - attrs := &cc.Attrs - if cc.Character == "" { - mainc = '?' // for debugging - if style == nil { - // special case - tstyle = gDefaultSpaceTStyle - } else { - tstyle = style.WithAttrs(attrs).GetTStyle() - } - } else { - rz := toRunes(cc.Character) - mainc = rz[0] - combc = rz[1:] - if style == nil { - tstyle = gDefaultStyle.WithAttrs(attrs).GetTStyle() - } else { - tstyle = style.WithAttrs(attrs).GetTStyle() - } - } - return -} - -// ---------------------------------------- -// View -// analogy: "Buffer:View :: array:slice". - -// Offset and Size must be within bounds of *Buffer. -type View struct { - Base *Buffer - Offset Coord // offset within Buffer - Bounds Size // total size of slice -} - -// offset elements must be 0 or positive. -func (bb *Buffer) NewView(offset Coord) View { - if !offset.IsNonNegative() { - panic("should not happen") - } - return View{ - Base: bb, - Offset: offset, - Bounds: bb.Size, - } -} - -func (bs View) NewView(offset Coord) View { - return View{ - Base: bs.Base, - Offset: bs.Offset.Add(offset), - Bounds: bs.Bounds.SubCoord(offset), - } -} - -func (bs View) GetCell(x, y int) *Cell { - if bs.Bounds.Width <= x { - panic("should not happen") - } - if bs.Bounds.Height <= y { - panic("should not happen") - } - return bs.Base.GetCell( - bs.Offset.X+x, - bs.Offset.Y+y, - ) -} - -// ---------------------------------------- -// BufferedView - -// A view onto an element. -// Somewhat like a slice onto an array -// (as a view is onto an elem), -// except cells are allocated here. -type BufferedElemView struct { - Coord - Size - *Style - Attrs // e.g. to focus on a scrollbar - Base Elem // the underlying elem - Offset Coord // within elem for pagination - *Buffer // view's internal draw screen -} - -// Returns a new *BufferedElemView that spans the whole elem. -// If size is zero, the elem is measured first to get the full -// buffer size. The result must still be rendered before drawing. The -// *BufferedElemView inherits the style and coordinates of the elem, and -// the elem's coord is set to zero. -func NewBufferedElemView(elem Elem, size Size) *BufferedElemView { - if size.IsZero() { - size = elem.Measure() - } - bpv := &BufferedElemView{ - Size: size, - Style: elem.GetStyle(), - Base: elem, - Offset: Coord{0, 0}, - // NOTE: be lazy, size may change. - // Buffer: NewBuffer(size), - } - bpv.SetCoord(elem.GetCoord()) - bpv.SetIsDirty(true) - elem.SetParent(bpv) - elem.SetCoord(Coord{}) // required for abs calc. - return bpv -} - -func (bpv *BufferedElemView) StringIndented(indent string) string { - return fmt.Sprintf("Buffered%v@%p\n%s %s", - bpv.Size, - bpv, - indent, - bpv.Base.StringIndented(indent+" ")) -} - -func (bpv *BufferedElemView) String() string { - return fmt.Sprintf("Buffered%v{%v}@%p", - bpv.Size, - bpv.Base, - bpv) -} - -// Pass on style to the base elem. -func (bpv *BufferedElemView) SetStyle(style *Style) { - bpv.Style = style - bpv.Base.SetStyle(style) - bpv.SetIsDirty(true) -} - -func (bpv *BufferedElemView) SetSize(size Size) { - bpv.Size = size - bpv.Buffer = nil - bpv.SetIsDirty(true) -} - -// Cursor status pierces the buffered elem view; -// but a few key events are still consumed before the base. -func (bpv *BufferedElemView) SetIsCursor(ic bool) { - bpv.Attrs.SetIsCursor(ic) - bpv.Base.SetIsCursor(ic) -} - -// BufferedElemView's size is simply defined by .Size. -func (bpv *BufferedElemView) Measure() Size { - return bpv.Size -} - -// Renders the elem onto the internal buffer. -// Assumes buffered elem view's elem was already rendered. -// TODO: this function could be optimized to reduce -// redundant background cell modifications. -func (bpv *BufferedElemView) Render() (updated bool) { - if !bpv.GetIsDirty() { - return - } else { - defer bpv.SetIsDirty(false) - } - // Get or initialize buffer. - buffer := bpv.Buffer - if buffer == nil { - buffer = NewBuffer(bpv.Size) - bpv.Buffer = buffer - } - // Reset the buffer's cells. We could - // use Buffer.Reset(), but this helps - // distinguish between undefined cells - // and those of an empty buffer. - for x := 0; x < buffer.Size.Width; x++ { - for y := 0; y < buffer.Size.Height; y++ { - cell := buffer.GetCell(x, y) - cell.Reset() - // Draw Logos star background. - cell.SetValue("\u2606", 1, bpv.Style, bpv) - } - } - // Then, render and draw elem. - bpv.Base.Render() - bpv.Base.Draw(bpv.Offset, buffer.NewView(Coord{})) - return true -} - -func (bpv *BufferedElemView) Draw(offset Coord, view View) { - minX, maxX, minY, maxY := computeIntersection(bpv.Size, offset, view.Bounds) - for y := minY; y < maxY; y++ { - for x := minX; x < maxX; x++ { - bcell := bpv.Buffer.GetCell(x, y) - vcell := view.GetCell(x-offset.X, y-offset.Y) - vcell.SetValueFromCell(bcell) - } - } -} - -func (bpv *BufferedElemView) ProcessEventKey(ev *EventKey) bool { - // Pagination is outer-greedy, and so Logos - // generally just likes infinite areas. - switch evr := ev.Rune(); evr { - case 'a': // left - bpv.Scroll(Coord{16, 0}) - case 's': // down - bpv.Scroll(Coord{0, -8}) - case 'd': // right - bpv.Scroll(Coord{-16, 0}) - case 'w': // up - bpv.Scroll(Coord{0, 8}) - default: - // Try to get the base to handle it. - if bpv.Base.ProcessEventKey(ev) { - return true - } - return false - } - return true // convenience for cases. -} - -func (bpv *BufferedElemView) Scroll(dir Coord) { - bpv.Offset = bpv.Offset.Add(dir) - bpv.SetIsDirty(true) -} diff --git a/misc/logos/cmd/logos.go b/misc/logos/cmd/logos.go deleted file mode 100644 index ddb979111fb5..000000000000 --- a/misc/logos/cmd/logos.go +++ /dev/null @@ -1,171 +0,0 @@ -package main - -import ( - "fmt" - "os" - "runtime/debug" - - "github.com/gdamore/tcell/v2" - "github.com/gdamore/tcell/v2/encoding" - "github.com/gnolang/gno/misc/logos" -) - -func main() { - encoding.Register() - - // construct screen - s, e := tcell.NewScreen() - if e != nil { - fmt.Fprintf(os.Stderr, "%v\n", e) - os.Exit(1) - } - // initialize screen - if e = s.Init(); e != nil { - fmt.Fprintf(os.Stderr, "%v\n", e) - os.Exit(1) - } - s.SetStyle(tcell.StyleDefault. - Foreground(tcell.ColorBlack). - Background(tcell.ColorWhite)) - s.Clear() - sw, sh := s.Size() - size := logos.Size{Width: sw, Height: sh} - - // make a buffered stack. - stack := logos.NewStack(size) - stack.PushLayer(makeTestPage()) - bstack := logos.NewBufferedElemView(stack, size) - bstack.Render() - bstack.DrawToScreen(s) - - // recover any panics. - var rec interface{} - var recStack []byte - - // show the screen - quit := make(chan struct{}) - s.Show() - go func() { - // capture panics to print error better. - defer func() { - if rec = recover(); rec != nil { - recStack = debug.Stack() - close(quit) - return - } - }() - // handle event - for { - ev := s.PollEvent() - switch ev := ev.(type) { - case *tcell.EventKey: - switch ev.Key() { - case tcell.KeyCtrlQ: - close(quit) - return - case tcell.KeyCtrlR: - // TODO somehow make it clearer that it happened. - bstack.DrawToScreen(s) - s.Sync() - default: - bstack.ProcessEventKey(ev) - if bstack.Render() { - bstack.DrawToScreen(s) - s.Sync() - } - } - case *tcell.EventResize: - s.Sync() - } - } - }() - - // wait to quit - <-quit - s.Fini() - fmt.Println("charset:", s.CharacterSet()) - fmt.Println("goodbye!") - fmt.Println(bstack.Sprint()) - - if rec != nil { - fmt.Println("====================") - fmt.Println("panic:", rec) - fmt.Println("stacktrace:\n", string(recStack)) - fmt.Println("====================") - } -} - -func makeTestString() string { - s := "" - putln := func(l string) { - s += l + "\n" - } - // putln("Character set: " + s.CharacterSet()) - putln("Press Ctrl-Q to Exit") - putln("English: October") - putln("Icelandic: október") - putln("Arabic: أكتوبر") - putln("Russian: октября") - putln("Greek: Οκτωβρίου") - putln("Chinese: 十月 (note, two double wide characters)") - putln("Combining: A\u030a (should look like Angstrom)") - putln("Emoticon: \U0001f618 (blowing a kiss)") - putln("Airplane: \u2708 (fly away)") - putln("Command: \u2318 (mac clover key)") - putln("Enclose: !\u20e3 (should be enclosed exclamation)") - putln("ZWJ: \U0001f9db\u200d\u2640 (female vampire)") - putln("ZWJ: \U0001f9db\u200d\u2642 (male vampire)") - putln("Family: \U0001f469\u200d\U0001f467\u200d\U0001f467 (woman girl girl)\n") - // XXX why is this broken? - // putln("Region: \U0001f1fa\U0001f1f8 (USA! USA!)\n") - putln("") - putln("Box:") - putln(string([]rune{ - tcell.RuneULCorner, - tcell.RuneHLine, - tcell.RuneTTee, - tcell.RuneHLine, - tcell.RuneURCorner, - })) - putln(string([]rune{ - tcell.RuneVLine, - tcell.RuneBullet, - tcell.RuneVLine, - tcell.RuneLantern, - tcell.RuneVLine, - }) + " (bullet, lantern/section)") - putln(string([]rune{ - tcell.RuneLTee, - tcell.RuneHLine, - tcell.RunePlus, - tcell.RuneHLine, - tcell.RuneRTee, - })) - putln(string([]rune{ - tcell.RuneVLine, - tcell.RuneDiamond, - tcell.RuneVLine, - tcell.RuneUArrow, - tcell.RuneVLine, - }) + " (diamond, up arrow)") - putln(string([]rune{ - tcell.RuneLLCorner, - tcell.RuneHLine, - tcell.RuneBTee, - tcell.RuneHLine, - tcell.RuneLRCorner, - })) - return s -} - -func makeTestPage() *logos.BufferedElemView { - // make a buffered page. - ts := makeTestString() - style := logos.DefaultStyle() - style.Padding = logos.Padding{Left: 2, Top: 2, Right: 2, Bottom: 2} - style.Border = logos.DefaultBorder() - // TODO width shouldn't matter. - page := logos.NewPage(ts, 84, true, style) - bpv := logos.NewBufferedElemView(page, logos.Size{}) - return bpv -} diff --git a/misc/logos/image.png b/misc/logos/image.png deleted file mode 100644 index d6ac0cf3151548ebb46246e1378a1bf9021a34ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479803 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Η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

6Qj)sR;A%H??dc%Q}%M<|!n8;f3Ui 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

`r82}crg^pS2z%p8h(77XP)P%0lV&sVGvEl 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 z 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

@8ggH6(QbobtoUx5_J36F?Tm=-SEx>hN{WUDq zW<*9-wwKs0Q6eNJ3wp%)uoe%a>fc)fepBp@=7$M4gNijoQk7jOyXeUb)7w=2gQw`c zh!chr+AF5XKgtNiMDEIu_I@{+o$7dg+QSL9y<*gLJFixa(jnt{61Z`-cnWniS0r{G zQn(bq0C`c;g7^=?A5#x4po}v>a5v!k0J<~zbqAE7ic3{r&dI?`e}~G9`^>-~9>Ta3 z6ajy%4D!ZY6boMER-WW;0E0ai)xd}oUV9I+;k`Nt5O%r-n-7d9Gu@vcF_nNC8r)qk zIr!qwCi|k9Tf#HiukrPYdw-UwWT<9i+=f5-JY1Aw$f8*IZ8_bnaGBfp5>_95jKBH; z6Va`xkVX1D(M=kEO*N@kMa-r}7aSqnIkw^+*Gv+osZ1bcIpaDT-;Wq*AK|#y;aOB?KKm9=E3dqa79ddgx{-`6r zYvZfWGETi82)u+Q2M5v-^=v~NumaZv7CvKQZRBYkKF1v}`%kGzfiBEe%PqZ7rbriIcK7q!%yP)-Vi=tKB|Qs)$}LXZh_orE5{AKCgE26U7@vK_<0_22z@k9YoCz@Sh0B-sX8W zt}o$!uf@iDfkOfdZhchyJ2?xQd`9p7T;iBMVWy%5sTeg9(tW3fHFz>Gf|?on=QkR> z>iSV!_*Q04vK*zJx{Mo=NKx)*!uH7rS=!j2`J@bTY_t6#6V^E_anf z?*3jA2{(&O4i7nOHqN5N#}rSUavdZjpO;Zb3MfYfo+Q@n0$}y zm6g2j0jD>6FkTe}6HU4UNH^)KCV z-2q4`wEv{|g0Gfv`!+4piQ41%oFQy_7PP>Ob?=o2{$s}W;wn9~T!{o<5N5SY#54^h zUi<&FI_}PboHgZrUmdUe3>8o9i7#K04O4P3V0(&=-6%pSd3U1cuMUG_j zY5umiBB2S9U19n^--gAkd@zgAiF#uS7iV<;R^y5yvH7U25XZ31*58BH_vL4ewcC&C z_AF^Qf=erIMhwS*?%WC*uQE%lDS}D)G1&F5Yhv^uPq=}w-h}>^YdW-z#7HdwxST@J z*PzqkWnA_8HL~FDuo?=~FsK@A0!Qyb%b<_UWlGcwo2MRot^q2zUQSj*Cwzlb;8uxT z5G$u4xKXBN$;WfpC_;uIYsQAMbeS93NVW7-B@a)wC%k_)R?}$(CzIFzS;o$ zJSwgcG%BLH>K$v#qzCbvL48%n@lS(B!*OHT&Icu&=`aA7-P*qYx-;o-F&H2;%)JAz z+gh#8CByJ@gV6Y~ZHbA{*f_#*B6kRYO5;Z&@Y(zL8BUsR$9&ug^~zCV0h`HWeIJMQ zI66D*EEF;#jaQgKz4m%Rp%dasCOnf*NB4{feT#=On{@%iwLMy zLeyA7CA+}eYD z`ghtRGtL(T&p$9m%;_pby=<*on&X6!Kk{Sc?dQPbD`sP9Lk%8G8FlY|L3stP`JugY zl^H|B2m43_am3as{mQ5M6`qDkCVyoXv73%#JQ-Rxk2l6&ob%LA-f>v^QD^GCnU?(a zv4vY@SU)5Qn(0)IE9M2B;t9=^NNJa_$}T9Dn?S~=P|iSlrPv5~Rrwb>PVi~1;IYI; z^}mfdAGd+D3+5gA_Jda!q`ofC6f0gS;;$`^p1cL%wI4H!>fh(vakF1o-LyMCY7a7( z(rvwHE<$@$z}z*>K779OM!)+!_XHL@s02OCbZs1!o9X>c!Fp4+2J*^JNM=(W{#5ZA zsjH{bW|A%Ghq#`ca6+WGww9i1i~`^375@G^@x5vI;U~>UkI%9J6|P*wcFYx!^v({dE6Q0*AD5v2r$Y7U`Mx z;xmfVH>S0IJ>?$ac`qVJSAj2^vr@>;$i!Nxh0@?=mOsP9Y--`Q5q1H5&4a{zAH@@hKhW^~A|o2X9w@ z<-SCMo}skpZF0ycoE|ujPp3x5*rxK#XlL(jLuLbNph<0FNlR5Jp*V*MTxNR83u7sI z?}O-IcEl7~z%|o;*UT+MmW68PYj|P(K z!m??$oXC)7?@>uYt0@D%Dbf`=x|fWOH*&l}9%igPMRpM9NNhy@DjI&!ZB3XbNFQv8 z89fMd|9nS)Lvox*k*tmiHFc~O>3o*Yn{4p%fkOm2_F%S2!gaa3X5qLs@1-~H*rpI= zmBoUIxVVbJpmwCApk)=ChHsuPe~K6{eZjmdkq6(<7hS=DxPunSKbeG$ZLu~iKO{hP zTiWmp4G1QE$?cG)3eg?YvA;V2Ndi!Wc;L^JzW(+Au};0~;qsx~8Op@=Kh(05XBl#Qd=H*iRJ|My{OW*so9M1SkE7Dx*(=d$W#23f@B(M>6un={a z$yM)qY*|rVqf1IS?{!**NOV)Li(gTmLNP;X8{@xIh%yebT$CIs$1j`qSJh{I%m_}XI%X|5h@=*ncOc%}QE?$ywZ851^L8L@nNFm6Z1G6?>dYBUF$Tb zf}!WQUw64IFm)-M-kxsCL%_Y0r6IV<34zh)no0Y`+GjZWrA`Dvd~I+QiiGUjt!Dot z5aeIXMNJ@4q-5gkbGiTN1Qal+q+zq>K2G`__c=m~uK3I?qc`lsgLhfWm8N`6n|BXP zP)N}kIMGNxm$11XeB;e~*|;P#gfe|9{>-Gl%8aPirvPG5k?gVq6D2HvXiZJ^ckRsS zSM|QXQzw^1X9(~YWxn%5y>&xvjqu?+Ejqk+Tij{n*YN{B6hg(lRaD|pb zzQ`Z1P@(7>FFqcQsd@)qW+Mq1E{BLWO~LbCP32V@htdcBR{3S2%dgdKsvUq}hpFbf z+ps?o`jaAy3t^95)&w@q0J1BE+U$ZRwMJVrKe5KO8fo<_q*%FYxC4UNVe0ulsar*p zeFP0#!m}IYBU_O_TaZ?WLcr=8ZD`(!iHzsiJs;Wdklk2ANr-^X^pX}&I>H9jh52h$ zgD@p+@J*)q0GZTu8m>R=NN2ob1JL5xC)q-cqds3Ap^l%0Oh7LRJ-rDzHU1$8Eg&A60zZd?x`y*7E>*58KN>Cl00?4@ zj1l|q_E{lN;p8oq-dw0OcIdtLWv|IPxcpI$UAuuR=pM zZ6Lp#fZDoB!APg0CEu1xQL8#fhzaQ7_g{W&{NEWrnD(WT-YZFGK5XKk32|g2laAT> z%gRcN8w#TDOw2TuefyV9rZXY;ad(76c2;}w>K@nx69trArl`Nhl4cR`p>Ewz`M<+y z__aD+oA++yky(buh!(f<7;n;{dk2JFzbcYm37kR+kTYRrKgZB3T*?cWIRz9}-phQ; z$~w+d7eOhV=+~VLo@-Z^b{b9VG9ne*WtXcW=&ML~vH+>t zL17GTgoQZa3NJ@eU~5D(%Z}xz@4?`hhx={F{^I@@1$e#Tl;Xy_dS&l=i;4_3X+{$@ z0D@e}fv`ME>kT~noavA1V5g3(6SaP>hC_g#_Xr3?lq|l%Ma;cigJI9 z!xt0WpV%CV4%Ycg8i$g$PBPk%!|W2HFk$gFs9j;gzl;R>sW7ot9HD8JiUQfm)}^nz zWDMdhZ=`wpF3;AP7}vfR-1HGX!AJ`Ty^!-c+*+Uz_~G3hMeY-1!7XA&;jR^x5oMwi`&gx6uF^fT9$}RHLPz^%QP&T)b-6)e}sdGp1~G z?Bk2&Aqb4zZmdX(7**ZdBV%SGkGg05#z(@44$R;V?eV%ZU3C7n%UXTB*(21ZI>R%sf3b?U69-jj1du{`aNJ#DDO4%0sFYw0PzrrV#@Kd9 zY`5(q!GqXlSzZ_P3sNXxDxlkrr!d@}uXW}%jAIjV4XPJ7x=&F{eW|bY?a^zwk4M7g zCJjj^Dg4w1e+PFWP$x8WJ>mT+I9r#^QT}Wlc&;nkU!opGNTqbs;3qY5;MBXA&HkW<1YI-&hQyS@%9QOLB_NEvfG+#urlzb zr8)5(bOsRtH-e3PWX?0YzVO&-u-SmFR@<3Ao5B3i zjY5tbM?Sp@WAcjE$=PL61fE{2F}&fx;xb4@e?pCR4=11@_k0Q-VOFvkeMch&b~cJ$ zy_4f&yWdh4C)AURKQ2T9u=cA+BBF%QUAXoEQIiv(i2^xC9C4@8HA}xQIV4lVA?gBr zzGi>@e>9zCT$6ve#u22XMWq>`AkrYx3`IbsQ3+{5LFsM=l1ev73<*K$ZbnE;caH8F z3>ahEbM`;yb6)JlUchH#~5_Qp(r{ID0U zHv#;_SHA>&b~y>T2vI>0B$a+h(MZnG$8RUsXK7%N!EoI#oK`%FZr5Q2p(%3B8j((toG+&}w zFeqr|QBdF*Fn6C2{BG#j({;S+>@ufqqWPU&hQd{<6#6G_bRfJtFE%8YZ1n)D(A z_uFc6`aI4P)@~=6y)yW5sCJo*7>%~8FZ^_Ur!Zp-SVKW*En0ym zmJL&f@+(f|*luc-9ijbrX2FfwgQ3rJU?k}SW_wHCDaZz>_313mC^H&AcS~Z$ul=xU zyO5N$H9|>)(B=qW*$|w80mzYkT3L?`oz*tqx!8w-GrJ%rw`opolv#7!>EvDJ4BQgR z+D`+1k>v^rG}nyC#MMwa@vLk6fi5J%Vb^Agkmo&wkT9Yw8b2@{(2Jm3J$Z@#4!ti4 zjaIn6IFh0RSg`jVws1Ur!p*HTI5_y2%&&bFSh`4j8@09$_Nh90Z zI@hFW1xdBmyva;Ydr(%E68%quPgt^ff9$CW^dcqg`u5qcU4GEk!cPqy$wJo=5?NMv z@q%dg6o_418S6Y z@tJ6LV99YMCV1v?%&N8G%po%V zJ>;I&HEt02v`>jQi-mmut!J}a8-u}I0%@qGN#z!9e@z?>epA&;D0jH4eXr`sTIe%1S5!iN4*qHhex9DEOaGL-!Xpv$CEIBo=P4T4I(K@Axx zcyl%=*Yb$|p8NqD283l*aYbD+VT;>Ie|JY#%%s>%`y7D%e_*aK$Qt}XsPw-6%cJ798iemRP`t*XS*|y4PBzextGGxy1Dq0p z6Gq9CGhhRBvV_Q$dFXT;`=Tov-b$QOy;EdvJqm&3b>B9t^!;A-9dTmd>R?lpfS_T9 z;!x(==4>3u-`kNQJE12%)_>m_l!Oq=(%Y?$ki8I~GX}e$-BT#8-=cfPdoQUbyKxRn zxPZ&aQCIn)I#1sq*SS&x5=WOk?ap; zaY~NG$IC9xw)EPq$-OM5bi=dX+zg?cJ%L(D&-mXJSgHQ<}$X8V8-8)JC(a}IAD%s?*#Cz zA7@@>?t@+!W?BL3UddXU@CCb#E|k+C?sJnZuHmW_C{sA;&+5dCHfw!=bRht|Qki80 zJ-Igryu{#5b8lE9hl(y}xmG8uC%l(_uS&B6pYEQ#mripWBg5Se6cVOFILhIkq6KWc zSrv1rUt@SrB^M3!Jqd9t@^YaATUpkGC#g-BP0O@}_qE~9^@vfim@%6hR(92lml!AH z#l7D@@TsN2#HB0~vAj@+tGw`{SM$pZMvv1nH--?Qd?$3uvLr?sy3%C4$7i(3UNN7V zvRHrSZ-jaiVi%YP2LGk9s?LUL^5~@H$N5RlwP&#!KsMk09j_?6?_e%8^xJvrrsg?~ z61f!^&nMCh$s|j3==$p>{`Yc^=L_{d$3P~YPsDI1x~x5<%&oBJK2__<{;GAz0F?zb z35*W?>JOzs*rDlI0D>r+_Sol8l-Titsv0jnXH`BWf6FT?#YpfYl6(86io_?drdN|F zlo=}v3QVW}hbQ=)THOBm!jNwBPMKZFE!WyKPQ5ov)Fjp)#N3)F42`rmK_vz0{bM9E zTd0V9_iKs#bSW~O!X(knX}N1V^J0Hc;MyY|IS?AFJ#jK$R3U&Dv`1kVV1+8?DAPR8 zqeZtgB3TYRnU$OUM?icB_^wY3O>)~_{nM|f4+P)$;{%p=Q5#-Tf_@O`*YN~Ki!Z&V z=j^t6=W90ckB|GM(is1PnzjWMRmg;o8M;~C9M+!;UA)VJq8A;C;KZux3Te3RuTvvUsJrw98WG_m9?QAhok zCfJflwYgQ!E}^RqV0DK+Zob>KT(JV^g*H%?W01EdD*iW7Jr0Kbql zEo7$69vkHxLnLSBwP%5`N>T{?h-TT(VbE~$g0zGI95Cj_D| zU*EvJ_oj=4g>P=he2kNOZTfOAyb|*%RaCS)9j#r08TLo-Lt(3LL(+JKc%6^y|CN!RI63 zIE<5Kq%YD;+4s}mg`aJ?yFOKYc|_~^e*9T|1q8CU%y6V$m_%ZuxD}P+OO?><&pkABcx(b7j%eSQNf-su0Go14b+5}j)+{b`1IQ9; zJ<~DT5`e`HOO%=)lP$COvlk4(+4#yCKVYSez!DG-DnVt%v&a%%FIaF+owQy{TJRUJaBP&sg0-$ zBn4$;*h2GJR-KZ?(I}|@=5})o$(UVqppJPE3>!<8%@QD4SX>-WD8QE?JTGme_tx;C zva+(Cq2a^n>34d%W}IPRVg5OpY5eEvuOG_FE`pV=|NQy#yI4^=fC2wQdVX%% z*-b3lW@@V(z9v9mZ@PhomobPR(^)J=chCJWu7iZ$$98UgZ^J#UH@d!^KB=8Z$i;{H ziw*%})$+(R1F7|@1xG4+!wGg#O9zTtzH{n?6#woaLDvD)Wy@||WVfVSQ{+dd?De8R zVwj20X>JGb?g6z5BUd3zelyV(yv!xtlcmw%a%Kyz5#5^N%&X+?e8a;F%3bnkyvT5GA z6n2kF(3QF%jEp1Uu4rLCLei28%;~m4Zplb+7;WX1lq179e<;2v6i1QZ>PmzqrC+$Z zT#+}an{M=;P8%XlUeh)P*St%sN!{g=OemNktH&s{SzBiLXP42b3 zP|K;KL`~*>3&6WF`s!2QE)g5TJnqGWf#bkW+!~VcbXEI{-3!3^1;c(9b>}alABK*Y zE@>taZ(1*}$7#CxhP>30WO1=|@i9NSRna(*yd~iU!G`ul$2`R>uuWhoF^7hBEvUWc0(8gOui+`SdAi}DRUkznxWQs?S-X`GC&QcH@^P41+RL~I`BN8BC z#Lg%Ly)mIE&PpgfC^K{&Ih#S6Gy9hjmh9 z_UOe41k5q5F7997SZnXr70SK32@eN9Zsv2ka=0AUAg{E_+Y z<^lZqE?%i66zr$t0L4--oKb4AyIoAK7%SwseLr0c8QuFy^@*3;&)F4!=+wR|nGus! zx*+C+Rz~0nDhacm$7kqSlN*MKu(mKZu^T(AW$Wts+sjcT9JYa^!hXCohu{HTWpM$f zGd6fg#O@(Dq5Y8$?-|?#W1wrM6-{oU?k|J?r~F9d#VjQBa78(wBd??AJ8!UT%{ANT zogi(tm5Z&jdkl6>1bzDaD}n+~bh6miO)U%~`brG75aOp5>pPJ`BBkqdU-*=6mi*>u zIYvm>Nk=@>Tc6m1T&hwiQ1ASmjzT~>yQhulTe+6i!61UA5zl+~Uz<6W7u>sdPsd_O zqPRR^FpOgFUa4xq@7@V+eh16tg;DT7;unAO{d<(Rm6wDUjZV2D2bo{m z#mCX~Xf{mCU@dtb=@&ZADCw6s7{-^AqQXi4+0 zA4kNdQmm&u;|gOvp4z%DqTRJ${**kDT||w!u9i(qlRp1B{G*Y9X<3xMBJKm)UZ?w1 zW`lzJA9*C)w3>W|BXV~mate`T zih(_vBSt3ZEd24Xd(J91l1n=L(T?5YXwqTT*!7$^Nh;d#6-bqmuyUffhuOMb{n=(! zkkqs3^Mo!3werxpziTMf$mFu)65W{k9PIa0CN)*qv4ZB|UsJ-Ob-;b|zsu>OfVgAR zJG6@D$J-giS-QQ_}Mq09x%3;wfJ{t&5%Eh=TgJii5wKK`MvH2LzG>?PdG)5l_-#?pC zRDIC8H=sEPWVT$1II?mIJs7+jM%YGQ1j%|!bPcPrV_2jp`Z)0~;~#OCZY{xm{7IU9 z94dWnMU0xk5SIV5iXg+ve&Sl62Q=C^|Q=cPR%r1^ne33bYb`5u=6cQpjWdYvW9-mPMG+y{>^|4dDCw@CXFP-PcI zACrfEi{q|n*As!RN-v-qjYVw?vyz_MLUbKZMqz*Ch6cH_Ll0RJz^sK@%TLon#qjzj zicK_e13qhDw%rF>oV*<{3He9dAJ9cNj?cjlZ&v#^@feey$DQS4Ha7nv-YjW7xp~>g zm0gj1FPKfn^oF!Zf)!${Ky#ycQ-fcLE^=WBE1o84uF^w})V z-QjfsC>p}kBFPCr2m_$v>ey<;631{4q@yTuoA05J{t|ig??$PRsF{9`;@>W)+Dd#b zm2ZVOW-zRyD1(qSijAVXrI?1|vLjvM?|e#PLWVLg!3Ez4iI9HlP%G7{;rcpdPgO@f zH3P%l6McGy?u1**rT-}T1Uws;kKR|de_6FR`QYF$wWQU|yKaA4B4vEtF>?F5|6hTL zqHt_nH04>apVFz2=kr%ymMI1I((b7T1}d0$=&QYdFBA6dj^Ve(7ku~%nO2P4RjJm* z#H97}kB?x+Mt}W(ngr&|MC|N+{(Kuz%0H*@gik1yaAMjatG4#3SWmM_KRr%ZMS8}d zZ}RtC`(W5eLS%ikju5y)@w)gH=<_C#T$NVCQQ_8EfbH8?3?HTE9D;h8ZztvERK;3Z zdjwgv&;yf|O#_4{qS0TWkBf5SLl&4$8m^A%^+gO4|KAIsQHySfSOYl)J_rDNPdyqT zM%I}z?)L84ktJqN6p*kecJIPkygX02Oc-^HX2Q&}6|L?k6CLI=7`TYT~FLK{z$p|}kdCEaPXKUZ71%9+9;kKpE?R(wl{*69E; zo0rt7F_57i(Kg8&8|1YSoMYJ!nXD%6q+p5bEX@q_nES+!tH`)-~_XP4%dbJVWiyZaz{NnRHc^(m|u+j;g=iGoF zg3jJK=cUhcPTstk2Zx4={$5@ruY*-e&q?&S>=ju7GYforQo6(LB4dym*l-nOGa*)S z3NJ)`!({sZ*oUw{RN%elRvRFX3|vTrGX|jFJzo*q{?~f|T^oJ#U!iMeECO?&bMi&`1uF#h@&O73XV&@~>+dCzCA`iI#*{==o@gdHEtlxya zPLl@p_Z90dQ8yLfyAl%kq-aoJep&Uf?#V)v>er@a$tfv!5A#ioKJzt%M3WB(>!|*` zxApq;z|DP% zfV1iR$yd>=HwxFkGUutC>_1Sss+%bo+yfZ`Sv%%zNpCyb$QQ!XSCRJ)TjlC4Lv}zm z!$l(CWIzU(JOw>7yuk?$qEH{Bv>fSW#j z-==vEGB1B#k7!h5y=jc`*J$4R6fTjz_Uw8iG%vV2e87@WAqDJ7;VcB!e_UpEw&t0j zfuq6O8alHGC8z(x!P!uXCt7OaSQHjI2V`ps{t~Ie5_?18kr1ty&jD^9W=>wIFOn3- zP3P)9ukW*llqTx=+$W$e@>oMYkn#z}trhD9X=+UHKpwJjPsMnozPwlq7}HUl;|K|- z_Hg}eu+tf4wz@*lPmG0Z#`%WxU9@c8l_tEF#;PXr9V_fjl(i5FMm1^m>b;3Uf!Xi|dXY^8K9Gi~p>wTeQ-EfZ`u;;mh|ll&fx&MePfL^r#iY#-5F za7?ptE^6FZ6`8ED6R-fkilRW?K@NV0(*|ugP6qN8`+j~gY{W`_oXfXN1nfKlMA&9v zR^=7}>xSe(E|>}^O$5E= z=ct-m_x9u&swwjV7hAAGncEqWJYOH z>RwYbMI&Nw?+_G6Q1pa4&P_?Ns(xHJAM^duBXMq}iOC6{M0&YcAGaMb?XUNZJ-uUc z#8Ogogtk6z>FLA^<8zf(Sq!%az&WGF-IK+uSPm6IFidfKBvbvCAraymb=PO@)62o3 z!QERUnX;-iOWE8O$OP>1(EWS;CiU7ir$$Bjan8j^#)fn_Yiea{f9Z}r0gH==z9Z92L?C}*)bJoeK0qtq z5^fp9ma8cLiIO=VbVU196Xv+}x}1>^MbM#I+o2sTI^G!n+pghQuQFHf!Ad{_l6?$n zaa(nk8HTkBYL>yF5pTV?Th} zVDn|6*4ua(&)*{FErxF)Qgmc}S6>6~efq`kmVQ{0Dwx!@|0TSyL#^wxN@jxXAsTcN z1S{!_rd#4Nt3qnw_oy@m!|?f?Z>T?WxfjsW0mUpXr+9qb2GU#``kE8EOWMCRIBwOS zIY8{2X=bQl#A&l0>~TOQMEB*^{AM!urqTsX&{wTTC{s_#i;6SHEr!10JfI=q`hKvp zn!_?Vh8w{o%T-T!$0tO=m90`d%v9>IGQlhtq5^{U0+mB5WLmE%`rtndo}Cg99GY23 zuwiMieO`x*wp<4;RRw_$*}0=ht_W90ZexCG#{{bA(tQl0Ph(X1q%x+%|LB}v%e9OC+{5qav^&0k^NR5Hv!w+m# z7`YSwk4ms}ass5|vJF`+hnZ0S*Z2G}Xu+oWlOi+HQdUGk6M!xkNVAP?7}P`lA;wG0 z!3*zLJz|&G`XA*t{zbTC$tp6E#^bFF&bq9qu=W>$GoZ$K7KhHGOQ`@y#Gjk3Kce|Y zAjk7(Sfy(Na4+Gj@AvfI`Qg>?Ox$Pc@D|YD3+V+1WGR4$v@CHu@eZ$C?LRW623=yu z|64uZkqumMiaULwXJSSkIPRnZ`_INg)Fk@}zjH2MtQ|N%xxn?ZNYhAs1fts!PVh3| zT7C=yV4rS70!XVJeQ^NqxD6i0?z@B`#Zf_W?f`tLWhw6KBTt`eg|B_slsNUG8DkUT z2`smG8M|&HKdq+i@~7~eptVG*WhssO*xh^9^KN9{2MGSL{gbSSQk=jbz zlQ7cQg1Y_&Exw6=toJTo^xfmPX1bjHP8LLj!jxOIKp{W2PGcJ%ws9(UQ_-QW`m_{Q z?6GBH7A9=`MqQg6@!p%nhHzlv+eNTXS;fMM;@h{$c5**X7?(4~F6Vu^CEikQn&&#& z&oerBhvShrL~lr&%N2YJJVqWf?K)X#2+MuQwtjJ94$O9z(BId;V=pGg{q>}EnuTOG zT4?b40I z$an5~j;ShcKD#^KH(+2G(_Kz@OqDCwrjfY~*2PIZa~&&8JHu)N=iG~x)M`KU)5;zI zOdEn#Y%-q6qrU)-)qgfZif$0~(vTLtnYv_RhD@CUq~4KRzS@+P2;==%8lXfU7lT`v zy?9C=Tle5Yw=fM=qR{i$O`bM^X3SMmoLkHnalHgd%R1jj46tyX8DE&enFGlOgNn2iy} zWTME98iRVLI6I2K?rc^R6(=vgwMfQdOaJ8a=M|JvDHu&{^%qHF1Jsy4A4veTns;H0 z-JOR%b6zM=nwyciWf-Gtr&erAgo*3mAaMhjC8&m$nZH|m+p+M~^GC-+IyufXB!TJ$ zpHF_W^S4;usJ0f2?eBw~b79L%3lTR8&YYZDvDGrpHqm8Eex}87vqWR6(pl_N>G)7; zt=+8F%CZ;72rhj?M3`4~Pn!K!DxE7SX-tu@^ywXRoP&2tOYn@sQe73giD4ZLQaeN~ zZ%+I&HICJchU);^jHX2p2UF=&yCQ|)?aPV_Y6g=oRg0a?3J&2FoLoENU1!y-3P>_- zanJ1&O&D-ZUv_tA`T@cQNs@eavNQUz)pd$t)d zx>6c%)cs`o-kgFxrIqH&cy3)kfJnPa>G7{H%b$Yn02`1@5nEvz++t`iG$l<5AI4F) zPtE^Kz89`dUFaYxdoN~mdjTv(*ek5CSnr0$?|#y|Dbd4qkaloZw5F4eB(+MV0^U?( z1t!HTqN;JTC%g@?O8#$R+R5NWkHl;E=6}+6yeF$QKK}9}3g~j}XsM?NCO-eLYUn1! z`s=Mfv-05X+RGmx`?&|Gq{c~SPtCIKc_H}RQ8)o)XM0;TF8Iiz$#wn1Vz4M$V8@kH z=YiA%lo7+W={=pY^&RF-8CmAPqsq#7k_^i?C{ta5VTL!W&qK$x<=vevzQAXFw=Z;s z>Y1L)NDMl8)SdD;J)(9#ZlxvKl#r59hpv@V`tn_7rqt~O$JdVc7C3f4rebjI@ybry zg13n5x+%7NqaP@3_kf zSV}e=a>C0k9{OK!XZEsY3)E|RvkT#cguZHPfxr}F5jICk+vPB=e845?O4jd+{H|IG zNTb~MEgoww@d%jQ1Kju^WfXGU*OJeLo~dZSmUvfuPF5}P#`Dq87M05z;1vKo!2$TT zu0T9zdx1QZ`NvybT}3(yuCK)R?=Mn3F7VQOWgt*YhWem-?|vtVp^nUxuX+XVPp3y$ zbb{%D%^!;_D4N}jV-g5Jf-W0|z!gHh=1Hbp`oW1597(J%pjx3A2b4cp-2Din zIjIM*o$YLGfE0i@{9jw(+DQ|a2lsHy+P!9&hKu1U+o5FFv(4^UH6Gwqp7Y{U`|ZD@ z0OSs?fT2U=@^cVua$Sf6VFB-PX*&6GKZBv8_4YBLY#*iX9gCw?KW?r0?ri!-&8$b( zz0pRBM=|Z1B)um+NOsB<%Fh&OAHQ%}c&>H{+JBNz3J&yrY#7}g78^9B_>E9KpDBE&qeU9dx9&YH?R(0(YU6imJRtR;U8C&!Y01nQ;2&<_E6d`+~ghqE*B(8sm~- z0f!sVbv&=|HI8yjmtF6C)Ild*^zQD52694$LZtR<;N?Nt!1sN63aI_3=#0)Otr-B4 zkK5rqDJ}hk8j3ifos`M?4s=uGzCq3U$-MXn!qF(~U)8SxPd$Q*Iccvx#1HV@5uJD~ zh~dkr^yT%=UC6G{(GItZ1hwvpMB*ITV?)ECTxgf1GiQyw(%T7%kb%k#^2mx<1x8A zUc>(CV^pK9Q@>%xMuE1{!M#hcGB7o0{vF`ML0@Cj5@E@h!cCeSl?YS&H&bO;8L$>R zPU`--)4yqhCVY96(KB3gRgC7@WeoU2AS7q8@)?kX@M0Dd``wvK0N3iD^j>|pld#ie z<0Qrq8>W`A(-o$`WVKF3JG6OQ=^^8$rwV+cnQ5**%GkYuFiDgL>T?o$u4rLEJDSDY zt!=wl*Y~%cHhs=qs3nyBrEuW@>3S5ArG9=mUnJ_npm@~UI)h@HJ~*k_CM=>n2qpSx2F zZwQC$bqZ~LVPQUXb88|!>_cDtx}m-hrx6zAK57>hGgoHw@?9D>uc%BQNaF5QhGm0Zsqh3^5*Ui`6WHxiA*Dt;gxD zjx?PYA1Gm_S^Ws%^AY*1Qy{tEsnR@?oWHcF;y8A^8-GyUEyognI z&LS_Vs1(^q_3^`Yd}e|k+aIL!k=}-`dvUeecC4FVY`ZJ(aB^MzozX#8k4!da*SCQ& zzO+ITS>vaSxCu&itpsI`emS;(w~wfX(aG>K zqILMyt5Z2|$)}?Nn8KAiLT?|yi#g&wHhc(o*MxrfrM@yhh~4LWB}27WvC^h$Hjm0# zR2FA9f*rkqLIRmD;nwSL8QgDN$xcmM40vZN{Azu@@y)sL%6YyFb2GW`lR{wHYX6xc z<_D7sNpWf4d0D_9tX{MZ_tJ`3U@~wEI4g-)zQe%XHv}#8dRL(wBp+jc#r{xVlQa!B6ASpBDLl3hU9tve9hes`D-T?NQX8ET%V4(dl#h!yQeO z`F7AE{C?iGFMt?74aR$U9!7hPWr=#qVO3wx{UH4`FmxdKXTrtGs~Q#Oo}oTdn$#4P zvxB9ifP3=`$sNCq1N@+nPCpuNelhXH-{YTLZJ+YyC%0IM#H7uBr>}A z(jkqF6}~e>XM<=eYJXlRpgvQc79Aa%=env`tgcI8l*>EP^(MFy4Y=yBj3 zL2!I$)oH}4&~@vsb`}RVM3zoUSk~R*{T6*8M2O8Vj1qSGVt@QEZiAiHq*mJH%v#di zcovdo<`TAwyL&3A3*@y25}}7QlZr5c=imf|;0*kiIb;7gsSu)v#7i0dgwqbcFC^Co zew#tGo&|V|ICl5+lW&|z4lGLl-{+A1Tj%s-x2br>E@l$De&A=E18?981|qYs-_^P)c9#DSaOU2KskT!RYu5Pa71A6aWl z{z|5u6$}{X!EQQ0$Gui2uG2;%yR+sh(ap%vIEXru$~qj|fG}_N%%+q&*D#w3tJ=$% zR}y~Zu97wAw77XbVE0M(o6~@B2kev$S=jReFUB}w73;J#Vu>F8>qUWpW*rz zAWM{ixE_XqdJyD{g{@B<7uSXnyS|*8NTcr+T6frJ^$|E9?2VDJF$F2%GI0U^dqc^4 zeW?O56{EqvNT9qat`WTw z0%z8MP1*u+9+4$fH`$>_Ss2-!>a{UGe-J0%@LhPnRo;6%xV-oE=C9Jy7sIht=c*4# zxpdJEZAR|n+-Kc|OSfEn<>ISelg`L7FrqGBf*m=xmHjFsvxj2LCVU3at16zt?$e9#A$;b4_zX<_Ifm-C>t> z>>CAAcNaA)mFpyK=gz?B<#B@J2EM~vCuI(cpHGt|p7w78H~RGes%GhCZeya#O4Y}G z;BMOm@*x7`Aj5?1b68#W>*_$=?0`^CuJ4|APm6VaHrBu?;EqZ6mYSlHpFMk${&Pjj z^ZI7D1yt}RP3UXW%gTW7$kFjZXbf;n1RGkdiRiDSV;EEja-rE@zkrvU)4al)gFct? zPC`^5vnP=LjGe4*^yxqAPL$I{H=|rW1k&V`@@fC z?(@0c>Ew&ztmj?vfBq6ZDXtl}`6)&c9bvXk*BU)@}P=|u{qLZ{5;C9l6$X> zRhPBAsSEqzZ?<3qhmdswC% zq8cxNNhM!dhdC7jC~1!Wk0ax&J)7GVqixp@+60o^&X-5J5EsxR4)8sWhZ8g#x#YJe zEiBSWiE6pgjRTihVL%lh{Uq`T+W^ftoEQOA9fldCIcAF8ap5T?2QQ<+-RxfxPTv%| zYTVN#&2Yy80*NdV{0F9LRLjX2NMU!^!(gH&4R{rShNr+AWH#xu z9*C(8{WfT}WYPrJYxv5q3tiIDhTYKaSu3K!%_yxI9&S4aZ2^X*uUVLhf4++{s7M$p zXXIsK%C;UevKinWg{?l=h{Wxi`We>yefs78Z}*{rDMa21-HjXdJ>#pVQMBE_VJAwo zK~1acQ6Fc6;Tvf1PSeiZgIZDuw`$CpCF7uzgRrN4MUHcRYprixG_$Ohn9Rrij!v6_ zr5$tI8DM@?AlWUPYU3CamKK|+eA3!o-_h}E6HvFC5y@$DOA}h@x1|8+`(PF-b(CzP zFY;YXLI3Xs7}*5})sC>sB*PJh3&xHJ3@KEYB?1xI3*8X4PhaXrj1k}6@SLXFJz-{& z@Dx~-vOS$Y>pzc@6Y2INP_^?sN#*C&h(DJ1tz^ZS*V#1`eN(u?*ML80M|`TmRV>s+ zk9{7U6;l&HpVex3Ga?hUqxF`W%g3z! zV^nk#nmM>NH>N=&`-w4L#fdqu8UUl9;%!+MzpqM~Ft9d-{snya zz~xM}sd-IhP=4zPw-O1Jg8H`L*Cng+KbYXz(^e{`XK%N@Og%P2UcQd?xG!f#-HI>d zjRxipDxz2@{;josf6eqF1FT&=G?>0*ap*Cdu)`+no*dVXZD$IowV8{gxV`n_+RtrB zmC&ao6I+QqT#j(tJ#vthg5$51+U&mD8B%Ee28Xn)GgoQ9{w92FC&4Jg)Tjc;F|lb> za6R3aMN~Kilwf%~M=__u)0YTyK!($$PKJ0#^d^?DIB00ACs9EIR`yY_R!i<7+*J=l zHnrID9_62I(aVgBfMdBr#|@4Z+p)m5YD?}uJ6u%M#dsjPc6spw zY_n4PTWQ&j^4v-V-Z7|dp;XHwj1zX8_IEf5o=l(m{rhWQ#&zc1$b%Y{fx(dp*G@Ni zD>_jSr{27gk)Dwe-BOm}==1T|PUAck4SoIkxB72I+`mT*9_4!LfSIFQ@28{$29*)n z8oUA>y=mU|sq*ZZ933PvEu(RG!IrCi)m#(!bIIG*_I+yelH96DPmxMkxO~RX;89eV zVG0$&Ph*|NQx#5K!>QB0u!PTc`OQ+#|4pv#Mv#ykSkJvf#*Ra?(zI#mCRCvoS;?a> z`{SRS@%da&)EGDsCcDg<3n!hQldm*;9`MN0V6+rN>K%YRn_ISOCu7ffmOL{z4Tddt zZ>?V=GWpCX5?+w}Q13O-3TknLw|~N#SNTLuDLggaXU`H$i)G@^koS|=0Hfmqk%~9? zY&`y#^S(KwDDaEZ*jp%TIYb|MFE2OOl%XMc1K@rlckzoz8W`-Z8&#}IHN z@q`4+`ZyLa;+qU8;PY<|%Y6?r-aW%Hc zT#8*b5S`($fSjJSKTx8`v78_rgWvQ$_f6G5T2j9DTm4PEWI1v;{pQz$G?AB&Y7B(i z;Zj$0;C9Bi9D8#RlUFuNoJO>&qysbw@bJ4*+ZoAb;&J!WPvyt~g;OZ*s^U?;TPL<# zAnd510TFiw#t8=lHX1`_dnD>yjrE@`ie4@pWQ`N7-lQd!m`#*;IW?W(yX&R3xBjSm z&C+<0$tIR)Wa#N|q?!7pq?LU4J4T$@oW)&V?e|^{NM_MhBE+skT*S`D`}!m7c(jtw z!=c*w$Grn@tfv~Q&JZ+UU$aFFBMTQZ8#^{UvC@F z7_1@9?2t#M8xS$Ht)JMnIM&X?5OBa;o6#nwmjaiL-`klv_;8t=4~C19F%nQnnt2(g zUY6S}vkmOs)=W(oOLdg+;IsQFCB>!A912n@w5x9{R9Bb3-&r+Xx^I(C?=c5_2iMdD z*YL~Xl&@(a%mKA=TZA&HUuG+X6>5TNzFEa+xuPFOpzk8QxUh$Z0(`uVv$#w_3l!Wo zpY<^8C1w~Nf}8A6^eoQGvL6^4og90d_9d0AK}oc>bpMg8tSTNsf020CDksI#_Wp?B zl)9%@>}GzJk#DOVw}n(rO;&!Cijl287Z&Y1FffwpZwJbV?ex@;KvPjACQ&u}to%_| z0lDi62@8*shq5HAFf3}Umg!$IT0c@;5N9TR)+9PVOyx+C$wxqZq!Vc<^_G0svH1PL zbGCZa2d=SV(IGPiS0TCEcHX4D-`Yz^RAjtp4nB=;Ynfq{Y6=4{?dMPD8FF~2qHhtA zn>=TMK-m>aDXx~qmydOlG)6|bD_c(xeF2#}!hzp9yw+HpP^JYp?0(TFUFsHC^X5Q# zcpHG=Wqtf2GTB#z!1tCnZIL4qyMEwp|DB_vS`S~7xwlsXbDaI+YQ}!h1R(m@3_mBT zn!oR|u?O8(OEPges!Pn7c}|lii%XMO>TylE`oi)8O~A$w%lyb-StPh+A2r-7P!NYN zYPHMEi~~Zng)JC+{mc&ya(JV`l+uUH=K-^jAi*p;KB$l6M*<|>Ym)Y5V2(bp539=( zcmIbx8RlxEN@ui=Ai1^GkqF*)g5aG`dnfBP8QH<<7u_jA@05r{QkPSS4jj(ENew`8 ze&(jv-qFe?wjnJAL{i66Tee5e&m{S1j?@`qNw@0NoC#R4hPw--*P~DPwpuD6l>>1= zQbqfq%{hZG;!IV<Xn#_jk!VuO5L5)UMRG?a=a^5-9bX(R_AuIHQ4?O5wk z5Gnqm_87uouJB$=#v^aM`fBw#821G9BuZw-GHZK~35%|7*TFT4Lvwhv+t4yQ@OV6F z4-+NCH7q@<{|17^ zQ|*OVusLmh1DbDm8ZrXa(X+dm|4=SozGN_{1{RtJ`7#T?2P_H$f|?HN7(2?-orF`6 zJR>z^9kTjiRZW5P*j-oV&gFdwp*6kNHqpr+x(^+!TjX7AD#Iirmlwn+32GouVQiS8 zHZym5ccDl&Jhzd}d&%@`cC-S%4n}IhCVhU*2Vfu7is{gM|qry7d}&z3KU+>PoDzZ~QR8s7ZUh6>>k!0p2`3XO72EnB7V@qb)} zM&#~4#fUls(8`ab<{U=tJ3ZkHW&ROApO6_;fd&2&d_*nb&V?zj$@d`p)L~Yl;^^&8 zf_^1KLh6I{3Z*_uAH?!I_T6sh)!3%GzN1DuX2B4i=*9DV>Q=_ur^j+T#LL@QfH^yPktFzn8Q%l=iufYu}fUFFKm zeh3o$1s=z~8Hg-fOxRp=kmyI#$h;9^67RhN$r(2VkUmcZhpg>pbXp;sY{wpd0|C~U z+3Mjwkc~*kVvPCWY&%ahm`Y)%^Au@m(UI>iNvXhCD4LNB6=uqo9hfE*j3* z1xcM#-@Wfm_xI*KT}FS6FOr8~)H=w7>EtM8U;|t(c!6MgwLpt@?G($Yt@v-frWyTXSnXzEWfCQ@7X+Gs^-7dZ94l zv$zwa#VTcZ+EFoZX+IlG^c4rI{Uq4tuzJ4G27Lm}wxM)|UEF}=AqrhuUcPu~@TVMB zU88(VU;NC#5nk@<7S?-m z8;u7-B_imZ9K{35CVhS+jTto6iaH448`vaq8cw$hB_R)6(;|o?vrwC`j9lsP%tn zI_t2e-v9p-5=x1JbcujShlIok38hO!T3V3q8liyHXe0*$B2o%Sr$`F}1ZhUM#27WU zo!@zXzSr;XUBJe!bIyI=ujk|OtZX*gC;lvD!Mb9!a`1Y^t+$VQ;2vGv>g?KUAz~~Q z*22VORn%3C>UP$M*dld4RqL19w6~3T=CS?&oIuu-EaI^jp}L{4@QvcGhvkg$=8mt1 z@#Dbc>ou==!lM0e3dc=rA+vsTZVN^8Jkip$^_CP#$Ub^=u`Vr zl!e&a-z#e+-K;BZD9w05yFBgvileHr^~scJuXj}~JL1jm(!)o>_m7>_A7xZl&^Et+ z&bAb+(e&+0%F(wlKR-juXiQyMDc!$Hh6a+qRQ4XrUZ{W*89@b9SE)CFm<5m0ZLz1jP6j90GB90zKX>zqzw~ z9oj{Ne0KuR&*KXl1+Uj=1ZCdNk^>)NUO9qqMJ4V~uQ8#G$$2GfS`Fl|K702&zbY%#o4pEyo7W9#oQDLILoK zU@i6?b~@I-g06lU+1O+8kQc^RMyBQ%<1bh*RqKX7YdO+T9qoObNF|lTH2EJ{iFBn@ zf~TAh7zuez@8#aTJ4ip~`4Z3xH>o*HC~Uie?4R(-z)g?DU-e)qHjdWBvPT9-gtdxl zL&aaM>{sy>7FBU?jE_{LcbVo#es@Gz;r%!LW=5(5bT@$n)9Td_mi)*_L0z-5GD@|l z3q#q7l*7o@us4B0vH|OGb2DYcCn)Y|e&5z-0V{ZJyhN?sp3f*7g?IIH*10pl`Z!DAd^*xSHU<)4` zB2pBZ-eFt$lkX;$pM;6X`~df%bLurBV2;BWwEjpW`dQC3Epgeo=GM2tGkj<*oQy=49V|WbCZ1J@qG`WC=8gsE=&p&aeLX$@!Pr0+P(dgER&QG6I0Q{7TkxSyYx5A~v^QQVQ zH|9-ieOqS>7yZpy^9`6n$30vejbI2-H8IzccnvbGY7ttL@p2-lxBi zBTOV>CQxQQreb&;!XUTR7(!X}ex%y1i5_u69U(Goh9fWo$1)jj<7k}#y1<2_z?cj6 zK*K*%%+5oFiUkQF+`{Vhmb}7^)Xf9A51NRI8E5&Ewjq1Jm~Q+^st*@jd$_KW@F?n> zO2$XDw^RjR3!r@_Yu@qo6B0BoO=yshbgIVA9)1HD7Y0M@X-siOF;9;LVpe9d~d z%$sfgwLsRNK1(O1-{WrcGkPbNr+d>re=M4;c%5+KS;#j9L;sSYOJwu;myUuQ03p_) zL*Vm6`G|q=@`k5CRZW(wd+wmuOyjRo*BN*3_0nfvDA+Nty~Yw+)j~4)w6Rpd2QHVswU*&rrvU68Lm`4kQ~Xghn8EWKxM1{Ab!3-Rg<$5-_i$1eYRfE2hV{>02CWA5W#egc|fx&Dd+)n$fL z2Dk)9!}TWgPT=C>tk4I09K$(qpYm92lH)!8cMYIs_M4mQCF0o0#jK+DL%atSJf>KW zd{-mvS9$kGs-$1vXB*TN&SL}O>M1Cef^7TR*qu(JT>Fq^4i0NxV#hKkE=dDj>PXMF zRgVUmv)!YKAj%AZhl$6hl2aO?M>T1l#X8*=YSb`d=v}9_@Y~3?aY0nyo~zsKzozR4 zB!zZ=?QYK_iJl3Fh?E=XgH3{)^z>`G9m9Yp)W$exyi~pUj5}^c?iFK@&w;fn&E^uJ=p0xA|u^q zvbe0=BHmDY8~5dbC8Lh|!hF19RL(1S)~T0E5|x##^4vO2P^QOwwFBP!^sUyK_eBrr z6*9sPL^?m18z-il~@9BuXS~6d2Eeibx2nc5p+-hXx zDM20|vz{e}Hkhaiyw>@&%l!S6hM?>a+QmKE_$cfkJTKCgpT%pLcx81c+uDc1CB6N0 zNLO}$k;@xt2isR+aZNL8b`}xRaklv-Dd@OE!l0>MJ~pOh7uFDcC{|1st<)cGgf9VR zugW8B+iw8r1UcsAIu3)3hZF=rH*{a*sApyNseE|IzW?q*7o>y4oQ=SP0;qOBmfrwW z^&mRo9@sT4JqQt@n9E1G>@IUk`AdY@ea?Efr!w-Da=k@%>qk_S$$95gWA(tEm9*{sVL3vfoaCXd`%=>E z#3ZB!v(RyIOklFM=HPRB6kJKRcm?ZYYj?aeJluy;jx zzpL@F6+Rn!$+e4Rn1iWY1=z*7X*rX%vw)=$73QCH?G_knU+LgIF0m9Sj$$M7rPr6N zXA9P)dY#?Jx8`Fy*JuQaGfD? zVEz*;edYQL0Hxo!^iN3CWgfQd5}qQyJUWtrttix-0`A>+c=FTN(fkB%+Y^tv#V?Wn z(u%94yP&&uR=-w5g|jbAlC8?!S`a@||RsWloGN$dM6&8~v)v%8I*dmk~b- z8rZ_t4h+Yqy~!!;!fqy$o;NiZPp0^}%s05mf1uXu-*}eZ2hR;4( zrbpA?&8U3-Fwi80X?QOIai^^O*ns*k9Vt`cy+&C1{!&uXRt%A4MrBpew&Uc+v)qDP zlx|g~;~Q&lzbB|gjt+Z&M>M9WbMe0nUmnE5SotsHpTOse2`Ie= zo7UVFj45*oZsA(E|M3c8j%YZLy=*q)NOV_isn1N!WPN}he@%7fH9SydEP8cZEP9!7 zQ&}5f!wEo8XKj?G1hBXOh{vVp+y_dDSi3rZq@vlk&=$d$jVk>}$yBecOJLVwgv87z zkz>~75HbEK0+RHk=w*%YJ^3Pj{M9@{fA8w0hE*EnXnoU^; zW_+u6Unjh(D_9MYe~Cm-n@+Z9nVx_D(x~e>9u6kuZd3MhJECIQjwky`qv|wYnDA!C z3?l`D3nv}AS0q}974Tah zayxOD@1y$=k|MviGF50#1|_9tG7n?GyoA^7U@A^-?+5 z$G;6!sbl!5(*ZuYSf^K_QiE;|n~e7#lgAiJ0xGIwm%!j!AFK2reO;l>5MsSXQGrp@ zX2s#_GjKRs8tZs*1P#P5V96dTnFUT;1zuRnI?d|0IHMgxZn$E@w)XB`&`VGAG0uVJE^$1OiYBJSg2(Z9mRb_8Y}Bn#i6 zoUqFw$0_*|zKmDBs;I>u9*V$9%l=Z6h;*c{HdXt;J~9l-{yKiO9w7&F>T|6p-{TqI= zTZz$7;F2b`Au>QgvAXJkuCaWD*{7erKOSme6TQ0&(s}upfAr2BzIORfo2K}l6n-w* zcQL40=4*K!k(aakJn7C~vPJ4p#JP^QS(OC`YZxn>fL(6{A!5UNkF2Oz`RmuO&AqTA z`v*TWnOSaZ-i{@CeOX!cH6txe{M8G8<-$x=i|pyxm~J~8(zvqYVdACvCmuN``T;H# z0bERBjkWA&J&#*-Fu+s%u2vwiwojP5>P0KtKwdq&=vj;XAhhceBcZ?3<7wHGy*B8 zMY!pC_fDX@E|kUH0rrRA@p{4$kz#Rj%l**N7!uW+r24-AS#WTeEU?%8uS2gB!%P?e zt`FO!-k6OeFXzIE3b{a9@iP#{1|AR-m3Xvq_5)e{9Bnm4*UNa3X98Z>9#wk@l~)E3 zc8}@}Hd<}a`^phRJ2v(XO&BUy8ekK=nxaT8O8g~Cm>SDXzyGIpKadd@gy`x%mazYb zN@(VxA@3H$$a+kiZg2?uvM9cOCy&E;C(l`)vY%k#`7}YwgY(u__?@1e6yYq=sSW7d zXPTTSdYl>yf+@Ig#hps7J=y!bX*B^iS?*!o6DWFW5QSZT{cMUB=Tbm`NnuDfs(Pk) zwP~8;dHqkmDydHN+p6p@Kr_4Q?Vk<8;F#_ogx=H$HtHb6J2LKEXo`SVP~x?2Ver4l zpUM7Sn;3ug$D%5IM}BYAfJ}HkaNs1!D{xJXhS_6)_f=n{q ze8jKn1r70({qJrrueSz{zB&)$9=pMY*HXN?k_O+xTPu8wwTz*o;_FZY8d5aJn1AtG zQFR%2d4a64i~dB8qce_4jEZjWRVdz>+aRnz43EW4TD@18+j(dK`;hWf1?di{^MubS|# z*Dx#KBNiOvZa`g6A=6M67#*OBBg=XI89JYbtt3-D$sL6b`hw5=e|yAwYx0C*jwP$V z#9`1668kJc{|U8O^hEw6|k8^JDjX?ct$Jff_cEL3z4K=)aB&hdDA1@nn2Dl3G7m zi0znLWQW9o^!(25wLfnv^x(~ZBZo7hmKWf~b!#t5J4lhe1nY5qqA`czR;l*Ie?NS& zqk(hQwH_GVGB~}`4NwWr;eNqX0ES19PGzsQn_u2rnu z(yjzQLNdTnYP<`e!@7_T>_&C{ah~hhb2gs29Rc-qHcz6EcyRozq_;}=+81FfW@g69 zcoF-LIHy-o)A`Wz6M4SEgi^P(AdXhw+NS=Tz$3s*sx>i$Y zaS{ue$CoIUCV!?ZR6m7oi*yYQAot&H7Go#AB=&8rA9d+B3Y|_(KJ4OE~}S z87EJd`hCS+#Frr^Fq%L;8YW>Ba2r}#3kz{COtSC)FwtGkEL>iwcux%L#r2bkvW<)w zq402q1SWS881pfVNcezy4p0sg=8@QvP`zbloZ`azZY#-@*_MVD z@{i}43x^R}%&}1V<~rc9208rE>@{i6exvcYfJ-%Ygrf3A%MudY9LTdSU@ye8a-osQ zI=k=;{Igx_S{8iYK8)F?wVx6HWd1DM=|9u-fGcIHc;c>9k3ylz!MxS~Ij7k@uFut* zJ^*)*1DM^Hl7D6{a?0r4_{i=jiPF6^+B|-GjCjJv@nUoT{Y1|b%a(3Y7Z3E~yKzKe z*ji!fk^9q&nZq}g)_d6wD3S=B$j5hN7Jt>#$VVHL#I|#ntx-}0N*s4Cu=N9!qbNUi zjxgQkA|3EscW-~Kbpl7lie~v;E2e{K8(|(OIb3rT;$-s~4V$5-CTCB=>+M=MHF_z& zS66$3li)0P1;A(kFd+11c_ve42G4()9y8|huItZ7LyDll0QU7Uk%ICpx zXJ4`x$GYueYd@<4m3}4O+AbhC&3_C!e$MX0{8f;GPOQ#9OGT8CTfdY1Jr!oZ{l5R^ z20_)e5A&g=3G-pfYe8OVyi=Ndedv2mhU=-d*CfK!Q+sV7RInq^{DIE%hJSKlC%;&z z`ZCSqH-_lUfe#?0(Zyst#vQwo;WwIpi0-oCU8-JZrkniBfdt8x4u{eUWu7EiNpo z|8PLkbeWsh<7prbX%d~2bN5T-Ac-=G;b5OLJ_swEJU@2M;M-bO^tI;da` zdLvjHuk#rMYRWfgd?dxi4NtAFQYRt&xac2}Wl$qb_LB))rZs_Bm-$xw4pXA&+EcGo z2+iWyN%`uV-j!eDfDM+-J~is3$ffr8aBumA_NA}My~7M=ZAodxox@_T)!|&OJBp`f zrSoKAG*PU#kAifpA1*$YeR|gF(5kxJOh#;0`um}0m$`FB?F<`% z^pT3O;#Ud51!mlF7<{Cl;V#u3%S(f0f6`B_unvG9Gtpc<*J1uit1B4}G~2CbQXO4+ z7TTk-*Py?E46OMMgZ%H+x`GB5I39@AzDponFXA)?i#{I{KkZPTdv=v@YRWipzPv>*HS%b(Ox;E|)lYMuwihp76bs{;+)_8<$a z;B=o2zqp${IW?s83H!qVo2o{ZUF@f+mmT1Lh%ROjy%qM5mC9;xw}J(ndDpJ+M5lgd z9zq@>fs9UK(!nIKCcyqPY)KUvPYYC6(SM2TOtsEKdSy+l z5SnMBRc3X*#D~EyIe0MF&%@0f9jvW2x)* z(hJ_E0gb<*wE^j9>um>U%gxieq+E3G!Q4;J|*Ljjv~(Arm%K zhy=#H)w59>zCT@B@$YdL?Yb`k89gK1_SRc*+!5k8?+zT~!0e63!P`m!nJS?I6)8oC zcfqeKim>IKdexq#cMaB~V~*V;gtf8nA+j`a%#R{ZB9LJnseGjh<4rf+66o9uI;f;o zQE3V$o}Nowu5?rs4>kFI-;+*wA9E`zzMH?VS7&nCDfMfXPb?KoZk(zWQ&=hT@_}qB zYuMuFysW>*4lr(O1wF#uorIQn3`@w5pI=U92YsKh)3Qn?h}sso_od5z=BNuCE~%fQ zYIQ9^&M_Qkzfo2){~O?*@DKnD4qpyHN@1rm+`^qNJxz%nYLeEGcW^9tiD$yiJ9p;J zqnEE!wDE-@A!UmafB_Ai3ZBCiuwJ-SB>Y>gNwqV^&XW#J6cIO4XtZ}pKp*AGWji#h zE<|CQrl4=Tm?_mcnp~`X=Nzi)eYS-&vMEIRa1>AY^qvCBP1UCmR-nvvW~f^NVZR_c z(CXwkOsuC!&jjHs0-PC?JBYow!cYm4_i?!cq!em;R~IwAhcMBA;8`7X&>(RRbFhLW^+?!8ya!|sipsTt9?r< ztRR#yI{0`w`GoI#UC^t*h81{HR}f81Fw;~CL2slIe6DQK_Fqx2JZx2gdF)R&l3O*B zcqn=iLwVN6#NAWCa_ro|hrxg14OpFV-Y`+0moR$wvOy1TC(_j}e^9psHq`h{6S z;LUPTEySO+cUrY?`|yiqDWX+X?Y3*0Kurr6kJ`P@qIkVXoCd}gwuR5Djmr0G&Q^Ju zqP+{`1~NmA5=6`nvuy4pw>Zl0ua7PqermW-M2c9p`lp+J*71u#3f&l(fEs#QbM;L&=O0hIjfB8t!i7{fw&*CB;J)PM);P~D&w-=m3W`K_8DQT)lN@c{bi zALP}7$BpXX`qp5cJJ+x_=^|+@78X5CAocIuo`jO>vWhh@ii6z4v_S!d@wQ;<2XmK4 zn12!fiLJm%QSN%48&(-Iwcfs(6BFulwGc#bD*qL+1^t9I;Go&SV3WxpqKPY5Ag7`Weth5V*Fb*Ggm?UIUXjX#O3yK6zcIPsVbl0~ZexFA z6-mi&A0iXrl4detKS1DIQXD6Lz#vEUEB_H>g~A!~nD**$+_xG&d!jV(a5`Y_fy zY$;I@)3thvi&`j2>WpDwZ2<&9X3`}ZE_T*fS~i63(`qQ#sb7cAf)tCD((Ui~KZuN) zljbBW$TheJx>EqO?j?S+<>|5OrLZS3O}H=28b8&&!!d4%Z+ea#`Y;3^g7zs~c*?Uw zujmg&8y^6ABC#{0Ngin@G`rIB^05xt9&;*IvFmV6I7M!D$=2ynPx-xZPRk3X4IbwD zxS4@jptl*fwDn_1$p>={$|*cFp>J%tB!<5y+u#{y{tkIE+6oOq&97naGnbiMxwnUI z9zY2i8)$UW%&oX`6vP#*b#H`?jXc00Hbhtf%PyR5OJro^_RtOjdlVXMFMV)rys*3R zBmU-6 zn!D^-kUf#F*@@q2*UqNTgTxbGSEYwyweAU;_lpIh%Xpq$aZEM^;rkt>5pToSBvPR7 zmXrgkX4^NLXOJo3Q|<)})n^>*lYhb7H@0kNKQt~dEDGP>nJ^0wO z)HXQi+yT(mE(*t%SW92qHoAi8Lz##>Cmit|MXj%5tVC5XRE$d9f#>7JSVgyA|fTwp0i zcR;+;yry-P6y)Eczb}~Te(e4jWG?tg@y9ZFR;R$XP099XJ73y(JT^7kvcHix8ER%1 zZ4uU+gqnQw)>^%sl1b)LFsErJ$TD>4K!1@SNu&E>?nN2Pw zKvg3#rI;Z(Ma`p@^4?hE2ok(9pO=IEho6TWHyRfKOsu0%sC4L|y!#?QEE}@EJ;JiQ z&Inxe^^K`cTi}iRm#*Elx%g)Jdp$@b9KUtNosr5gc`xgSYru7^x_u7pt)<*8EC52H zSW1>h7h}+=Kc+z~$^&+bFJsOimr4KPT>w>r43tVfe z6@t$*oR$M6-0{W9({1P9I%dTj3qZbOh8s2r=BEc*Z^t(Tp1m0!%Xeb9dNR>j=`nt8 z`NW@9nw}Hk!_c7={t+KpMf4>JL_Bu0a-P9@g#vUlVNg%o;QkS*9S#zX*d+rTufFMf zj>t>t3%C1b$ai`3oLP`iQVvJ$-7bOozs3$&2CxOO>~$>;KQG8ujeYiF*Eh&-T|KMU zED7xVBzGs$D}~|hbj`wep#qJef==*&LZz*cvt4d(VK$y4w*@W+i%_u+pLz!QyBgM4 zhRU624jIiu!5h}$ubGyvl7{lP?+wjuQ~AAReZ-I)wd^bmj6Wi>$OsOBQLY4Zv|VUjXN0bwiFfrKw(AE)FLs1dC*T|F3v%(rRT(r)Nec>^Ga z5NxJvSDtCqu(CL~W=&Qzc9I0lnSn2ESd7mD%omEI_maIp$rB^A4p8_U&t1x9oALq0 zux1=_3DO;}TbLxiGM;-}&Un=Dt?2b3Xz_1vLhJI|K1a?O_l{Su2zndqCKYGxuvj+a zjS;LZZ(T|Y#^PD<{UKcVY40%tttg-x@H&&NDoE^<+gRc>n=>=CGRR4Jb}P2!EX9wz zC$Plc!9mMG?Y)G$MNa$ga+=|4I)|SZ(oQJr>caooK@OB;>+BwTd!dH&*eMk@{ssJ^L|^xswx;CV zM;+atBBy9H1D7NnZ5%lw@0*80E=3_X(QJMO_3Y;IMfoi|WO8ZAc#sp#lE9p2o{Ds8 zj&<$4j`@0^5I8PiJKon8cQRl`lF@@~*|z4Cxjlr$)ud+aFEMQDBh|bQNw!CpA=Er& z*4Hc1lIjG@1i5qJ<#DhnC{}&*;PUlz8*i&l-@|#ebK3#L{6;r5CgP<>6zrz7XX=Qs zKzdzFTWM9XvZq(^e_#n8SkLO+t#u7cscdNQ#D7MQ8ijd$gI{`uY`Iu!m0y)yKL4y9`;qd>dYWOs#$JkV~}0e|X6DdLe}RImj=zUk?d4 z(y}w=3k-s}_RpDgBWfig42*m`fBqX!prnU}d=QEqB&110K23+t@bv9oojUiUa#rZO zv&F&!A!(i5UrABQP6a|7A-Dgb&A|7|xEQeSdLIaj%h;_^0>UoOq|@f=v(YS~n(=S; zW|3o-Pez(u=?@kzufuJute_p*Ljs=ONFDzWMd=}<+75O0pWO0gMM}bLs7ISx!ORGo z*~?sPG2T?V6A{2}{>G`Dfc!_TXx&i`#G16wuQ3rGc(-H3sUVS>88=6x^+}+_$r0=K6Gj^hqmDYv4#bbaB5n{6E25+ku zb2EijMqVECtNfqp zG$GuTx6sPc0~0?aTSj-+UwBTAA{e$5wu*h6lFZ2O&Ffo>$j-^8#h$l}5G5(6-q-Jr z3K6xT-G89ZX}c;n+U-e@yvrWY-AkAJUX%WX=}3yL@Y7)dXY+P+`bo6$$6{BhLj1vd zgyGd|TJ!ecBx_M+ky7Be-nM0$Hjat?A*KjfQ?A29c2r8G4v`!}d!)|JG8%AS!Ocha8z_qC5cg^V(>IlXlyH+J_<7o0Hwtc^*g*gE74u8gV2VP$?uFv+CrdnNof3Nt}=U3l4Pz_d%3{k@`$(o z#O4=4$%Ip!@vB^YE4RWEBV_dIACQ!M%P=3+r7Cuw&^<5_9jP1?g!PhU7Yp+B;uLYm zf*(jMtGB)3s>ydLco>P(TUp{Y`{BxvM9z40Nv*WN)e-GMZ2uY@Ki${wW(5X?M8E?qrA)Xkezk0>feU+u%zRC+19$Xtch6)PQv;}u3e$id0oh(h0tJZ+5;MsAvrD>q5Tq{tJD4#vvOa#0|T44VM9aST&ubyi>i^Ns!UPRMeUhc57g41byu@FFW4IviZZ-(9TH4~-#?gq$#}TK1NYp70Gj zu!NK1`5rOplb_;%f;s5b0{QOz1^RFtZ zs(g`J4U6dAwCp?q9v+^kfD=D4~$PdPOL9;@(tNvDh_Hl|Tg z!VP_xq%XkN~g;#O7`uS)odrZxLoq^o+i8xO4W)rv!3!~WK{A+d1>4Ax1;(6#wL?E8S{XXo`Vduc*n!-;dK46!;w+l9QaeDH*3=E@^>HWsVA5buDYx!oj zVSf<8U?@RCSCklreM3O00`nKT7 zWd6SkEc$XER90y}DJ`!EAmaQ5PQEGX?iEvk^FKk$Hopry&(U9bPbW9i@u+B6E>2GJ7GQE zV$+Af&*Qs4u^xva^Ps^1les_AAaHY$cwmNm%ewAlH}CE6g@}~W2z(6^UnG5}xctgw zTChGj)I}Hw$}~ZDej2p}3^>pnzSsc}pq+sWjS=g+fT#fQ)1U;s(zyR0Hgj}*ndhPV z6{-aN^{{-v{3Vcx_#03ax$aT8bA`MU_AWUIzN2CreJ1i92t;l`<}i66SuJx9m#vNe zQA39_8U@5=ZdoM%|15yJs*D%5ay|}tWTxvSQ-Q40)_m>zuD)=Yx;`^g; z_>^gF`^k#a%Gejh6}P@N>VYgeEumu{hcY@sJ%;Q%@H-H>e5%Fg?dIlunIlV%*+I2l z!dLxg35)XnV`hj6v!4CO%uE^o5i&M3d`?kS)0w4SoZ$>?YMtK`u;t|+k9cfiY%J*K_oLyj&4*&vMU}EDnxn7T#b27^h;LO^bdF7D zzxOUfe{#OAD{KB1$97{0^B-`7X$bpvYkzk6KI5GqKN>ib+;#n>$f%ACMT^^8x*vbA zTzqYl01po!rJ#s-nz+hgobN7HE`BP<_NvCUNt=jWQ2bI=<_2WxLK?FCH?fm{{V8T} z#b@l>>S83=^`%;q7pT=RYsT_g?C{|_rAk*MF{py$YdOy{_qDy%YfUXJc62G*8$(;< zRJ1tS^kpr8!uEcc$zP2bs2>e5ov27%Xm_!6k9_JacsBr6j0h54>P~zfi^{{;06&fS z_w5m6qUVdrlHg;PEJc~MS(xsgT!Q{10e^4`ewP>^{)xIlf4Vl*YGq{XUUqi}iTsm73MQJE0HMEakMVhw`EppI z$Qk}rfLpjFhs>e zBL33fQuqykiDFiS706dmX&0O&JOtjJ0)yQ?(yI)52jS}x1moYgWPMMeoq=;ousOp1U zr(sRkzjMcRSiPJnGSIH_RHOz_?&@Ax+@;S|8!k+rarQ|+P&|(1tfI9w+%W)KWF46Np88u4HJ0`-VWR}>s75In9EAsW;P>DQt7T$Uo7|^( z;nq;fKZh}BRh%8J3G??`XCMwyPg3|Ik;_kJJIY_!s;m$)f{&FPHY;;L+kXmU6BjQv zDyMAp`)3t!TR|C^jGiblZBJw?!`I{UmZ>%&UbuSvk>}~1<$!lj(k^ad;ei7MsSMNM z6#e(}0l9E|=Dzi6;u{El2#rX#4(EYrO6NnBJ2D6xhN|bh-ck&|M;q|w;9V*JsdKDb zF*q8Hv}h2=^CbZBGlFYR&uE-~&;!M+pUmU#y6%B-AU;PY2U18%geZP0HTMYNtL80cQBIlhmRKi4GH7NQ>Jl3q3@Z0s|ZrvhMnG5Du z3nO_SOr~KMt(_;8^iOq(@kWXDs~B&R!m);mKc$~rWtYU!B}L8 zwG#cvaZ(|%z~bFucXyn9qEZ5TR*oQeWG~dA&LwV&Y4j2fJ|en1cvN6mE;saYFZ~o-+`9`A_N4NsPI6Q=R1*=pb{eEopQ6!`pb| z9xUoB{5?$9N-4TshA!dtBB7F<7!w%gqGa<@Uc5ZIK20I`hV;CK8Xw+8b8JR9HClAk zuz?BwIJz<3Ak0+K6LuhMRjrXJHliu?RA_fSO`DPBe+l1O?^osf~e9(PGT%x34g7F}f^_%*a${(ZsUHG>R%4fhHBQ~!Xvih?WL$=v-tqEIK$b&tC zasjDs1nYq4mTb_!F^va<9Ca^ju}Q)s-c&aO?Zl6E)o`Y{qq`;W59=P7Y`6v^w1JBW zFe~>MNxcT~b?-}9++8=c&7$g+1a^)YzwQ_m-P`t_e_wGsk=`O4wV9@d> z7H+twc@yeWrY{*+)?AE;EfPhA6-rnqOf0Gc<)81^qemj@pP7z)@0yN>{}ArGT+uSH zjV#SH%}9tkRjGI=Qr^ZxbU4fzaf#ZcpP!8);uonc3b_#-NzGJm;QnM!KqwO%MZ|t@ zXy|*Ou-wZ}O<~#D*$K?jB;bK1S5Qmb_9SMU=`rix70bI%oE)1L*9Ua%kPi0DQ(qsS z4q96F8yXxF))|$8wd9z}-^p|zg+;yYiTwltaW^?Pi{@#e=Vj4sK25Hlho954?fY`Z z#DAzU(d`xq)}2alest+Ljx0KT0tNECh|P?U*C0lH>+!uZll4RKy`>+p>`qyShn9h zSN#>t0sJ*qL}2#p8h z1Ba&O0~|T7fsRo}O7}jUXk6dsElo%{M^bX0{(5k39ZA-%)cVC7cxy1gcNpDG&Hq!^ zcq?rLX}-`XcBJ5c(X_UvNJcQu4)zxflTxPqgSbAtiNQ@=Kt!>7t>zw7-SNZKR$H0E z3CqFe3|riT0BD$54LrFc92Mb=O;W^wHgS7Yxs(6o8KrvK)c{4;6-E9suJxLs~4M?i~^CQpbjI56ZMG6Vr3y;I z2MkNRJ4u4e80?p}f3!+Ki%?rc1Ha#7*y9I+M5(2Rn*S?(OsMkQp-?GR0!buI_sCOr zDL|P+DZD^J^v)Snam+@>qc#Z=uw(jFQ(S7Y$pUqR*?1-pFRrx16jS~%Y(k{g9r_AY!My`C5&J`cx^LL_Q9)H zAw;--($}_YMk~MKZv_k7RHHZL%3o`Y zb(=GxKYE03IJd1|JZ^sbiDjAeZQs8#!!KFzV|bxZuCS8gED1Og78U-+JTB!~*0_f9xK|4oIesz$v|6x-?3A!4OG(?h}Ue3 zk*}Q1N~<_PsnS~r_Thh+Ny$=8(HZ|5d~!yDahDmj)(sa4X@2(iKs^`XD+}GwY}uaB z*i4QhA}R%~Fp{jzJKp68`5XO4@0xkuWq{WXO(!OvfFPDK!PS){mM^vt61B^LTy7mD zZu&yy>@uc`{wpuFfdFul2Tawsc`TH3`*Zr)^_5gNloxp6pyx%DLQLOhrBZ= z0=@D0&mSg#xSEu8%Snj>cVXZ)ZQd`EN;xTv6*>x=x=2nK`njaf1((MNExYVeY9qF=L#9{e=yA- zuf0_>*RHU=Kr;YmfqJXj5(fm6a_e}yJm`@gW?Ew0a1hxHl-Y2=m;BazH`ORg@F>Oa z_X(U!Q}XgYhPm#Z10S)qXCOmNFv3c~#HtX4x7uuO1pV;7mMSohGwIqeR93GHY?)|e z68+_I0jVhde>9zUG@Jkb{_Q=h-u7rIRccmkF{@fzOKobl_Fg5n8WpQXjZhS|YSboF zNzvMS6MM#vNOJ%3Ip_DyUpXh|VcgcvqNtX|( zXp_-AgGr8v#KE(F6r=n6(PYs6%&)r$JhEo*L0+qc0KUq#6$qCZopcy!99NXV#h=9& zfGziPb#UxFg)iq(`X1a;zp(hA(>fPL#nuOF*l+}<%X$y8dPW3_eX6@hvP;sXyTS#l!RnVZ_+dR zPVd?5&KtI`jT7xBY)Rt2<>hwi!0K$D3L~=PhVCU5vOh!VEaiyj_6l~obQK5IX}mw# zK7)tY-sMr$SmEuuDqQs@4%xhsUO;Jt;ZIG$lDc*y$H@b+mYYqN9#=AJzMoG=8iKLu zykKN1pBu}TZ9aQV)~>74IHu(a(dBTyy6>70ei8lzXKs3i$7^e$<9%j+p)yXqec|{b zV+fl zP;}i^u0f0O#N@TO(YpzUcz8i1K3aeyT}nxQ6&tJh6}94+K{e#WxavH<`$&Yy3eF;o z*yW?4zAUp7-e%6ogy{Q)qC>A=k54pwfIZ_OA7f;S3$#_;U`QB`_n7`R>VF7DjkQd0KN!9dPW*$kz*bV z{oX4s$P&uFnnlEBWQ@J4{F=>~!YHD73Y_9;{zVbEdT}P2i{Yaoa@RT|M&Ny0JpV9# zoT_0b7Blty=brDig(ewFmhjNp$D>_8(~FfA?;bcrBP3i>L*gF>5_HE4IVZ$B+n9G` zUDp;VFO5fd2ZfliwzDFzY)I>_&T!&D&)2y7_=_JDIDUTNS5{trzLH+P?C2!Bsk_3v zTstVWQ-|kL60aBrr)+PY>GBNWEfoh_WY_f~)<5MdalMXT2#N@zTYEA(GHLYQ)Z+eA!AfHfU2JgABjO7PW^%oH--} z@0HVR`G#$INU8nZO_S0$`2e_Ei<(!4$jqb9ky2k`87Q^Q^T2jt31~P9g4Eij<$s!R z;puw=J=&FwexqOpwm1O4M4voA!(&QDzz4}&~^R( z@L^LnBv2*Oj2J0jMJmON0i`=sFmX3ht&acK<4XX5Z$gxtGK&9*!7(97=>{i`ob zN8b~Gi6NmMJoREieiC~*$?NvT-z|-PNT~3(>(G+)xK?G?DD~t&k{Y{#HwP+9N^JO&h{tZ<8Qv28kNHj9#f=o&m9+hLwqDy#-1FwHKfM2Q{Me$+n-!rn4YXYs zrlw%*y2TuRNtl#|iI^jKWW255__@3)j^NOZQQ;1-E^Xcw3OQ7WS*(d}#&7mfbTF?{USD0w z8@Qf;(TcS{Hl{+imaeL$2I1+;0(EBt3SivGmI-LZ4f#!UCw~dOHE$`!;9W1#w?=xk zmJ;Ee)eCJ3BR@ipu=tSFw|`5jD|qiD=BPe9YwX7<3nW&N9?)Nd?K2X4;}wcu%Vdu~ z!A=b(yY^eT#en+0u1l@#8TNtH*ckbF;(sOUAT@Z?9%4u+ZK&WNjIVZJQP^N63BjUY6{I0so~7p9?m5O{M09;r-M736sr@_bMH9b z!SUVB+-QBV&0lZ#`9*t*z8?w5-uC&7kqg!XHG^PT zockWE?u6nT;+Ud}GrC~5h@gM`4;0hHr!h1mngN2mOt81wO;2(=g_R*sDB(b-OPz$Q zi<(m?;@5~;4&m20Qd+v8yF^J3Lg)uR;)@-Ke-YnLwu$a9i_>%|!aH}r8{qT0|DOjQ zL8^8v36N0d;Tb@2qMSoQy31v~ZzHeQtUooBu7QuYCyow#!W3N zFA(efA4UAz`Vs{Pl$UDz0lioDuXj&@uvPt33?H_NJ@|Vg#1s#mD~(WEz5qsSz6S5X zdEbC##g;YW-Oa$ZG>9wTs^Jw0TuFC9Z-2t$8nAc-mNcnW$z*n~6~_icu^~a2!hIm^ zbauOqU6E;S89zxlSm%Lz*A*LY%E+q!2^Ck`49n^Y^ZIT0-=QMD~-K$fpf{z~uM z+Ic%+kc}hj`-N|Jlp#4aTZwu_)+~d5(6E3DJ#QW|WB?r;T3!x2jqGSInMe&IFTIv{`!9PWVH!$j``Sva-rRb=XZR!_5 z2%9|tR9=ex#KG$TWsM=vg?;nqYb$OUomhM!?I*DQlQ7z}uRDatEI*MOG$b+)(K?YZ z8M6HGB4?4PUY|mS$Ihb%?;>)pOS&b#Q;!;G;X&wJbia@GQuK9RFl5WHv}`Zbwh`Z~ zjQg$j{{k@NEV)j&C+_S*=xd#Zi)=O*_(M$6 zUQ$pC%lh_|5iE^UNB*z8Wm2Si(DHdJCVGX``N`De+{clZPvTZ6St*ekvi7|k%-f0Y zlP6p>+oDUvg%n*qFV=lFj|WEXTjnvmdJ@Ruq!ZK@j4s)5Da9U>R;OUtA}O)_>YE! zTQ`#fjrdEq===+odpMQV$=Z+|liotu@;qJfAY(MhoJoj<^1$;2Ag6Ef9{28fkT6PE zRO8VY2p{(hZeKrn;t=z7@nNsDy`90IF6x8PZaDZCF(D*2R<)8kQRePMp4~~?s?~zI z=f?;qg_1fI@--_wEv{~+ngrLzMm<6>&c(CSzgB#oG+{~CpS-`sN}YDn&MF9+@nHTw z=Qw?zd9^MsY-bBO3KU;>_XW**EC=<@cR+c|HWLnj{~!A4^d-1lkfS}3mgHV&y+gvK z5Vj;;@AuEV7fbrw_2!VnleA+%5URY%$ouob%_6FwrQ!XohpGbb?ySXaGTun(fUs8+ zGTrE;-Ip&%Wm^LSmtan?=e&!^A@nC}(}}2+23awwD#uX4XV}qX(RYM7J_dT%W zYokFQY6A5!8K?M$g8O5E>-sCM>)nmfS9!sB7$h4bBk_|@CN5qPc26Ewi)MQ#N_d-O zv#~$x>lC=sv#kz7Z1RtjKVPd&|39eMe-!`39ligOc#C4xSQt7FdW2Z)taP6I%#Zu= zkoQObz|l&olY>jlg<)O!4&DBJO~(*(d9k?0QT+H{`{hZ`hb^kHe-Ykh^_&l7885;@ z^NoMkce;C+tzUpk5GR2dju@dvc6_>Zi7o;8?> z7dsE+k9ZYExQ%qU+0GYO5%y8$7$mbA8mg-NrFxcGbl+)oR%$JHpRy4ra~WP({vEw2 zr9l1CU@VVkTdERfWi>rLt?zH@58>uhkE6H0jaJUVZEb*U#saNXPP%x)H@K+BstU&8 zxreP>9}Y%CcK)m&>CqLQH2X=%c!Wxr=Xv27`1G^!Rx1n>+fpBD6=^Lt00ki~SU^{@ zaKsTrIjefbc^)>x;pvns_`^5757&?XtT~xwuvmFw$PS#Q9xrk8yWRBPy=8@4j>(gm zZqAGApV-k!{q0Y92tKkGXvGx_8J99l6efV53_bG=WBx4|&m?g|NWDx>faAAbfuI6y zCR>b4zgki(ej5Ajz8D#?ri%(X*$nPPCllfB0uV0R!$edV+d}cSi3ppEx$ zY}{)Q!2fvxfJ11$xW4Sxt6W24VSJg$m9_A>N5_#&Iel9N-{(Bw;G{iI=4UtO^0URU z@!qGSu)u`c7^Cjc0ibpleg;3L=+Tt&=y6)j(E$^quR+)+s?L{(PYIV-zXO5sU}UEg zLV!)&D`F}zV93HI>;XrMdxop0jR+Qf#S{@RtL2~bnnjgZ43}L7?s#bfALyP0kBPau zW#R!CvHcONzL-em5p=w@^uK7tdr4nx!zrYLV9jMF(C_~B9nBm>f7ulhg+n3H2u3dqk7+OJfYhCQx0 z5wD@ozG4hA9>~2iJ>U=)%n$go5TTR_PTdkcw9&_$2RDi7+i=0T(W^Ui#Phhr1l-Q8 z4T~B0CH9)3Qe4Zs^WNYsBoY+nt=v0M$WmZ?3c7=9&g;aQxXV%nZ>9pQQgqJzSi}-LN@(nzp^slMAZ`~1T_Tk zep|C4hv4eS?qoddb`46#Ic3m9Q1%Yiol&af6MoL=Zid@KKjRLdU_GzNdaq)(_vJ?! zv(^*WLHlEcI%u7MzVCdVp2s5~lL7DOV__aUa)fD{=jEiOW4^g{T7A^>@aqTw63E*L z|MWT#{m2umbZBcS1t}7-z)`S;9G!!YvoHk!t5*@!qxFFMYFL;jobxE_Fd9csPIG7p zcqMs=V)G2G9)k-)9A$8>i;G*kgYZU3fELhjL;i*YK>yn5nu57tw(!G#F;BPj;yyQW zzOfYrEI<+RSsEAmRUiJ7A>}|iP0x7(8hCJDNaT?3JADT?aDqcd^OlyEpF+?-jBkdt zc($g%E6KXZ?`N~&^W^CGF|m}%f&-hUShw52>oaD{pf{U(kM|Gl@KorP=Nt__*hMxt zbqUB4&t%ybN|EtT53B`Klt-(#?$=x<6duQPF9L;VSj!dpm8Z=jcn7qIE2?Q502g-e zv*ky*-L7Wfwr)WKd|ey>c@!?zl~lxX8V;@f%Y#Dsf)T4>y0D%=0jGao9IwrP!{LwC zOtpxwZT(&(eMZ!hH2dV-8k0J25J4fbOvjPvI^@p;b*E}DzM@KTtxCQzSFA6-< z*-)JMZ$OEtD?i7rOgPu2M3uwD^TXSzoyI-ih#Z#V3mYtkS}&`TRL1AQ4?*-BIi;Jw zQvWL6ekHEq@06q>fpGdZ^0`+XP%L27eUbIt0Va9?OA2uz7Lh(*8sEx(1wP6_s`N% zJeFls3g^5b1EEr8Z?dia+q8l1XBv;lXB;6nH6tXOSY+g*>CimFQ@ao?>mXIVLZ5H= z0H3}9XGqS{*_!(D#YyaS%O5iqo8QxzaO|y=2A$l0^*CA%Wwk6`mYA?iB!CIEn6r*> zd<@N!Ygu{}&lOyHaWt#1C%bjm42?aQ2lgq~pwb7qnoI!j)Xy*KrBEW)5&4V$a)5qA(cHkC}6@H zPCe9re=?HuO}H+nnUJ`WlE+5 zf;XFezUe4*l6D%FcMOiOKl_-VHMp*&n~u;-O$x_MJhAlXWA~X zYw*)B{_lMP%k39-u6c`n%Pp`GkiR`>4p0n(YJrcuG0xX8B3-cF4zys;ruHs&AJ$W$of94fwqI(K!pK$q)RbsMtczgw zE(~pw!Ql;+y&h<7>X}v@4%T%Z$sZsQ0}yT*p!S zE2^|m`Ykh_E~ki~wc8$A4liW;1;sbl4K9{zoos)#F=wCDv}jWD@U#6*c%|2vchCRj zlnEJMQJmxx6y0~sCXrZQh?`anZ2q^CibAz4<6r)af=T+L1QP)p;4f!#EcN_A;jVsF zMXChT08@pR=D@Gsa_~3VeUXlWXVWDgF(D-& zylO7ye!g?=Ke1On{A0bZM)#3%VDq=vuNuPov{F)~#5xVWnZ6qDWqT6z(e386oEPXQ ze4|Go74(N8*V^nsd7-}mRQSRmOXQ|ySsYqKeAar3yCrtl)3YPhxOH&G!gkZNri5B| z-%g0R=M0|E7H~=K%xJ3O7I>I+=*TWwPHZ{YcY?rv@4(5NY-r+68oZ-A0eJ$TjDxs) zyry#Mby8rvo~F+oeUp;eW#SxVia`_a<}a`?%BdC94sa?*ptpUuY_j2U2WaRT?J7^W zlv(nZS&RzLF*JoUFn@^qzyPlmF1C`a=`^UQ{2 zXNouN{-qWjLzKC@wXa0eV`RF%rt6Ir^+s=X@qp<*7}QZwIUrMeCA+@A&{H~hV|%K$ z6~&coi8x8{uQP0J5wrLY4aIx|mrW|1G;5L|cC14ZID;?7eej1&l97#WE6x*UUr-AK z9iRGBrFw$h%yz-J?f|a6p2`9f>)z4bM&ZPln`3;C)OvD#ii=gu86eAzCtr#Eba$U3 zjv48FH?C}O1G*F#*dlrd1=-+y&}^BGqF8tz?8;$WW5+vV?go!S-djG20ba|j#yJ0 zV@Tfi$Z)ES{zae@SbO;J8utSTMkkb{W&5S;@SQLNaXCB^XxaKp?q;e30JP%R{~ z&6V@Ws>fMcdXWg5HLJB92UU)_HU*r><7uB1nMSRDEC!-1?H|Z9Ho#K9vK?o=;&xV2m`p0$7c(U-`gHQwDoc6nkXYXprP zXM(;CK>VeQ9B;W-3-qR+BBo#+PSSZqWpNvSWS!NpBtZ+KlnHTX8lvQbHV6KRCJ>yJPKB*`w;m6>ont#o>7;NM8{b z#3o(@Cc;fx85ynipliEtvUr_|=A($Vy=8%xw(cOX+e!MyLWpt)=9A1Tn+Yo)IFmlI zWsy5L=JF^37ya$n*5%{ft#`uPD9nWdM`?BVw`z0PyqN=iy3Na1fUbC|=VSA=_Pc}4()BA_-# zxT@88-UqZ&j+f{_HGpM$MjIB6bv%cG|7gR$wwZAOe{d0?UFbot|5H&_p7j?~#(%_y zady|<8{QOy(S=pGlWL$iFIx}FjUL-Nyzpk9E=AOIR{&-y!Rl}R{?IJ;Gmrbkc`y4% z_sY1|qR+fd`DoxIIS&}O==lyfzhENg`_sXKh2WCm(4p~we*yNmf5Sk}XHbCnkJfZ0 z94G3S3Lr!(;C@S$IhOs-NU`_b7>x*|Wg&*Vt>+TPFyb7;%5pCm!6iB|;Bm5zouN|Y zI>C(am_T>(`P(a86nuG!n$PV2ru^;%SihKI|z{ikOdQko5FP4@Tq%kCTzTh-Oo zX8Gg4^`+GASt#BwVxq0C9-Y~LM9kxUv`OsVM}3(FIZNyzUznYl`IgbbQPmXtoD?!A zs9Dg|>ho^RurJe3ZJ5F=F+YVI8f-!^N0@kG)nXaD?LmSFj5)Wx z6K_1$Vq??I&>rapjfaLR$GCa*f5;~?R~*$I!d|MEjy;RfO=b;F?MzW5AG$wJ>VwYtU5{3N zveGNgK-_LD{OD)cYB);|b3U;wmt~s9-*EZI2mwwJu-s8o4`>1Pci>;<>pQ~Gyl|Ji z%k1WVCa?L#OR=dPfD*a=vNP07LD!~QuNrw@L^Co;KVTc_U1qXp7f;|5y2Eh*@yqVy zGO=ZHro|F+;qwRRc&iwC0*y(lhO>W{k}gPwW^%3On`dbobpBd9$*2WS=8gcY>&{Mfo}c^S(cUm)d5z3QGH35KeqBP zZ{VaBe_qA#dzSN@pCITvl-78Py63Zo4?U%=-bY;6c zy|*rhNfGDY<>8{41d&g1G`nX+Mw7j~Je>bdJ_AH*O_nq1D-?9-a~>VY#V(?j zpB8q<^$|B*(idy6I*)p)zFDeUN@#N%pvhAI!-rFUey7kEok|@bl+}$&fA#N6zoeLN zyu`ew7n+$ho9`Lxvd*o{PswrPYye${WBxRZF9`Z@HW(ExBzXaCKw8D?pzQ^dv(Lr4 z6f>`P=EU|y{@Up+NkZ0N~9e@CR?)VBcTlz^X5IxB^zVm0HCxg4esxk8#(h zJ7+Ied>3taz)F{3YuqE(Yy{L0$ceVQcQhjC#^dGYiL{YIih8+NS;;KzwK4~_w2`*9 zrl8V-d<4AQNZ(D(5D(*>xlAWSz|6EZv$r$xsT6K@hcBP@164b7PkCZeB-kwFk`Tnf zP3}QHBCzb!w|hz067TcVoCoPkdfGT)dmE9Iu;`iqTNh_w$u3rIGV=y`HKPd=5ufq3 z=tbZ3yqh;d5hV>qRPWz^r>w3gjpB-!uc?W0=M*RNtnBJ4=pgzjT~YMO(dbC%9e%$0 z82&r;m6Kf1)5=#JO(W0R?mT5(F$#TXsvcj$_c{GlXh&1?h=7$Wdr)(iRafJeFYNC; zJrSPOVq-OvZ=PlfKh9WKV2|W|-lFuNQMIKhhKr1SM2mL#C*|I^9=M3G>8NvCgHsO? z)PMM&e%ddR9GxgSvJGvJb?$ir!>Fw|J-1|LhFk=tKzOw!V%g?R@V{@PV+6$f@4Y7N z$oYP%WOU+%2=Zv*?f<^^Gv_xEMacOQuTi8>{9;p~X1WTnFe67wqrt+WS@ldJzu^K$ zyu^$5de3#vL?7B#(2oG*VCQ^rcbw##w!hjB9y9AcrdjnuSFk{PK@0J+Av-)kaactQ z<&nC@#5*>*_nCKJ&+^;;ajECjzpekA?UC{2^4)K+&gubx_bC}VI`L~W@+FQjxz4P@5&4(>pV8}%hceB2HG2hTTlz%8{@_~w+z)q){zLjZf zAwofFSSUqTXyvhHSc?9sMRKF-O*LZKJkym}`L&{6zLoh4ausiHg;UXkb05N!EbXv@ zjW@QAXM~*!9Ieay#G;}}2d){C&Ga9B%Z5G$$Cs?*sOP;iw@axCB zkQQy#F!ku3!Jem7)|#4{epESbQP0K=cT>^mkjmOx0ercMsHnh4L2r7)eWZ_cGxMa7 z=EGTe3;mC0k27DzPsvQZd@a2j;PW!k&%&aH>(A9J342rB_wSFQMPumN!>eQ$<_z$A zDx?DIG+Jd=z37PsRiT~#>%Vnp>zJy01DhpnMCEFB2>bVPa^LGGGG3=^+}9)Htj=;) zSu585n!}mKVXzpNgEY$ZnzL(gnsn+e?7tn*jk4!#+`A>o)iJl)P+$#Dyu17BjngFj zg{%pWfBJ;>6x5xBp|tlXeed(nRgZ>7E7AdP3!ZdqB9(_y#K?I}=*OvceGnwV za{}<8K=LcIHZ7>ut>Xi!uytsY%6OvHEbOtG95Hz+s` znfXk4!ygQUYh|yM3Lm;y`E7kx1)}(VmLw^NS%7aIjF|=pX2S~aOJ^zu10A^4voWJ) z(s>ZdCh%RKebO1O#eg*|NUbwZG!<6>k{e zp?eastRlAy3g(raRTeDp%jVUfy61|Q(=Gt~Zqz|EXQl+5G@1%KvF&Vf6!vG8dzC#p zM#{*)YagFvm$BEhbT-x}kR5wAV+y?O_)nw_`eE$!E3GO=25yHg?nDHgBaMZcR3ap^ zVDf)s_r;x0SAG8dEQN5g@qmZo7i%3bHRiz6VbM1}HgUwy*jTYyu61^~GQdd{_vPvq z>^(N5iXQF|*aG^lK#8wIESt5$uNu|DRe=31;$m8E=ny>PuBTbpJtUirgVO~q0rl9u zLEP5XY9sbWYM)1K!P}I<-O~Xaq$cFGA&T!P>bZOB(34O}!Xn%~^#i=7zqavx|B>hb z!VF%3`m6qt2K@Ai28!*HS$HG>bAZP;>7U{u1^Gco7lT@#Hr^^)SibtJ35LV;cu={m z%jt^=i)pPML92VhR`7lye7yo$R+8HH=d&0Bv&nY9UouRXL-82QhUgCp+^Pkz+5Z_nbSD+8TX zcs?B+GEBst8@#*xoE=|!mJ`mj5I<5`oi*@HplbA7KKbc^>%>SvyW`eEfbV-nZoR!3 z^7bte@^u%Z4tjZ3Y1WR(Ljg}c*?Hbx0eL-cIt^?AF#r2*fOs4-lRHLlO@mz~>$w`q zvU;M0|De`kZ*KuR713huk2?4Owlz?hjObPkWeVeV_9HJG=W z({H!l1wAYgHEXmh!FOP1b?|X?FK6|_u3^JZvS2M1g6gCWsDBxyZP95Zz`Ct!c-3k! ze4!lM%b6^9P85a@I~Bjh&H$~{4+w%>VbGyI+>dbhr{Q>R?-=;aKR_6X9xjBpX(eX^58T2lX>4D-URhZM2n|wU`{W7#p7@ITxnc*<#NSvI{ z=ehSa#R6s{i#`e`wEH+UE~P4(TQ=+hzFTiUsK8WE1KeA5yOGkMQeb^%bE|Q=cE)B( z8Q_%qyOv4Ue57krviZS$?+>mr@4MOW~%kM9Pk{<<#f5qJ2 zrPBLHG}@xv`DEObV|B2!T#ty8CZ<{rI7RtlL-+s52mzY(>rcukcE3m=QS!QH;iu6x zhfRC&FH@ne0^B&jzRWxg1AUf=s#T-8|lUP z>Tr4G5!QWt3+mUeZ?}VDuB2rw!UlrMe?qqIE30Jtm(is1GpWw`G*ZgxaCg^yTWz%<((->haXtMQs<_;{`-dWJ$c?-(crUsp z{}m)xF&AF6LBhH8D7o<_&nq!gcZfTkiGarCSFdeK^f5z(7Jm{^D=mjadJj`EFB3#5 zrGtGg(pwHCWaNs+PSPREW!y4x#AL|d`Pbp7w5mD+>Feq@y(}h^A zlAa?q+~(x1$fE-}*1B-C+^t9lo;9X=usbODM>^@h!He(j*_1p)xCs1FnKI*z1*O~dcTIkl~#$})l)%itk!S{SOFLeEDOaJuqR64 z)}qV2M-;j1ldNQ#ZuV27(@bm!$L>$c4fSv(Z%*-4t07t!DdV|+5mPWcjV>`B-}cHT z-m188wkj81Dhfp0xro1l9f0)8qPmy5HiT3^PDc}2+_7HV}Sy5~PPe|FMJySS&` zO=G1IN-GjwJLKshgR4)9^J+96mA424Eej#*9WFo^#}3X&`wxP84n`gL@d>~ITNWVy z#QqPR-wi{sWrGg#N-rh$RtCUE(6b|qFnGvV^!5M~@52bR?FwEgP2x89IJ2KTbdR(Id5D8sV>c zYsQD%yw?$}zU*FZQo{ra3S*}ERyxk4Tillg2@IVH$S(BeCn83{c)a}KJ@+3zgS-6NoH2of1j@R zr{+X6`@MfWS5*DLj;J@{(uu3Asw*#&F4Yc{d}KDV7tp}D0dG3@izo8G@4e_NK1Ro% z*V9OXI8-U2S2j9w4{-7(UyN70bEqS(Lse*Aem<^O#{kqTCs`0HEw{(_8kYnv$n6M7 zgxTGnLV4MoB1oRw+XlY1-MFBX`JgwPS{xnhCd8S{w`Ti>)kM+Iaq{~2&$-r4TtBF7 z|Kl3^y7cc2uE_b3bzyB0EY3J)89PF9X+-7z6SF9sspzO~6d5Hw>8zUa>m zHlj6AV(e4eiaOt_-4dRot0mdUG3O3Ur0!MLR=XEa>UjLPMVyX({jp06)E>g>(EaGk8vC346cXjPIPWD9wHgD#6tAxH!7UoT_r0+$;%gLU649Mk8KVxH z72_mQb>PznV0uibjqx)|04LJ(G5{Eb-Ezx2)`eXKkKo9$Z%-h*geVGp7K zOLQQDn0{z%z3(}-;KfpxrI^&Dap@~ut(XMh#-lc~{h&Co2)6O>(r4FDtKO55Do)`I zcQ}qTL;voJk6yL<%AeCpw1(F+1SW#NR`cDIZy(UH{|e`&?o@>CC7+MXen$G4uVAm~ zea2VoO6gSSQwkN$wpVNL;f2Uc@gtSasm?1>7rM1z+!qa`pa^p9AQIsUj$oC+FDI798a9@AM9-8Q{cm&`s09b3 za}iJkq+xg%R0j@yic=eLdxDdAMtBh#4RC_*-&^z+@e=fsIH#cjHITz1$u-26c+A*_7)q zr4-O2Y;G#(QL}prRy(jVxpiWUYujC>=`{5XOk-G9dG7(Q8&jm;;zIv%ufaCO+`9jb zUi6mD?ny!M>72*JX7+DJTjIkvqMYMpw331m+%|VhVgYwofp;HX1%M{#2UZ0VjDzXP znwPwis~;&fJDuh-y=)5UasRM*cCDROG}AL&bgw&l{E?QPyt(Pz*VoiKsd(AGK*d9B z7k1qT&S@!Lyhu1Dd;Zb%C?Fo^3I!K>52ZC53)0kRsjB`3x=UeFH?V6@WEC&i^a6Y3 zn)ovivnuLdk9EaL=C`I>@ zZoxNIb*CDY^erb0O^k7D@D!py_JX$hmpmO}_&Z@)bqn?8hqJ%^pdqpdmyF+q`yi9Q zGU!43RFEgQnv!s>i9bK$LMoxgRD5DZ?5eMUec8(|GP7YQ9i)=%sF<2)smDp7=-h z3>>dW4t@e{GRPhLN=i>vZ)|M4fVfL9u5zG@6}S9s=U_QN*EmcOXy5%&enoyZJiNL+ z<$_zx#nK}N;cFfXJl4WJ`SUs$LdE^HTwW|eKlJy%TSnm672Qd$-X-D}Ay4P`kag5C z&{%_}?%L4*6h=VKemBoAtvZ-AMafsI zC*YBbqTAb7>iGnGwNc(Gdm80rROQcU)7n}@H%>qQ?d{QkGm9^udchxj8*R7OvK8BP zRbVndCSeSEqtJlgkG3pVgpC2W7Pw&>aCET`t*Oo9*`@G!+gMKbGaS_Vb>HWsDNHP0 zz;1Eq?Yj0Zr&SQaFL;_>;gq%&@$!ViHXSnn_8;J>%VTFKYu;LZ3hTI71x82DMp{#QOt4*adbGrGTFo2 zXhV`%O;iT)cZY`S>9!xAJ(*Zd;fIYJw*KNCpTEqQY~SB)G|#S;-=mTtFB;cUQf9r* z>aL^XZ%XDirA!tK3^}`?tN^k%>AjK{oAH}P&R^4B-izv^T|e|M@Jk1k=owpiXoioi9uT$@#fScih5GQm;@seXh=*d!)j8l2)lu<*? za$M^bY6VZYG}h!+9_1e2!7Gygb%vN!ae6mF?=vfinq+gB(lC%?Fr9%HeNC-Zm728is&GWw&>LAJN@Xw@Il1OVMfWVB&8-f4jcbOZqF9igdmX*#C9Q!wjD6 zHTagwRY$petZ7Fcb!`}PFnQ@_{n*oSUi(XHI)<*izkr6~573e-d^=LZyGm&nfWwvR zM|-FcWmqXWcundiX#I^$q3p?^50f5g{)jb;G4HpyRcPO=Gu7LACn8&4QPKRAh6wtK zD}OhTl%twYo-r2i{^@$XhcKJ?5pcu%cXC!+Net}kVimv6={qYbmnK*T7A?V`jFF3> zx7jVA;M+VX*v$@7Jf|FRc21waA0`3Jl*w=H=Xrd~;6{kSzwPThaZ!!NX|;X^pkvQ0 zu2{lI4RR=^?0S?~JJ}>7L=}V{$+A0%Z;11`oqDuPKd&Mu{-a*%HJH0?TVdz@<+NiG z&R^K}t8M4P3}gzIq_xnQ1?}v0^yOrOtpPWYyvD6{j`<|UUb_=J%nls7*wKmgRygQj zURT)p?0_3w1Uj+*7FSmmZ3Kd|GyVE(?vbt$z@aI9*DSc@*$e6)lWR9jY$@uQa|JQ7 zjv?Xo3`on`j@?4IbEpW44ay)iuF< zx1sHiDVz~vua;#FExMcObKA#u~G-HHP%wcv9;n( z@)A6;O%0WB6xSLZ)m{+Jnyklh68hYxr5sEPKj3z`(ElQ-nNs*c(Q%OpkX5@(W3kD? z`@IbQ6K%6Ow&*gq&kDT<5ElSSN8tP+DVH@~p~Fe7!qDq3o#o^U&%hhdO|p>WyR%Ii z=Olz}X!Zx>B-rty_0(su>D}!s9A0!4ZFMER_7>^94mbOSleXQqw*~Ekjx&RBU5}#_ znHLC>vDPWT@@Lr0Nq}a7RW?vK2W75<2{qON@qgQo<==H3^Uz>5!U|m*%F!)?7*Fg; zKrR*n{?m{>dz^_Y5rh3ge9o>muNhglUI0za;>WLTp3{@ss8zf;C?V>tZ3k83%D(*$ z=*x#Ca)x0x^U*C^<-kymH)1pW-Q;VrPzjvGh+UxXC6EQ}>VBv286XEeyW;)IcCgpI z0gTE6Tj>BWfq{vkOgpo}G6Grjm8KQrh&jNxd87;%&1jlIe2?d&Km$dQ_rL@^rYg=rmG-2!N62W~`&QxCJp<8m3V91! zDJ?$ATmy!Udq%RFRORQpW%|uu*KZijE{JJMAdCLqh9-z<(?I;&?-IF6Hwy$HB7YXC3mZvEPX%Sy%Ne4eB%*&_wJRQ+!@!nv)t76{=sbwm|Ta>F(f zPunAxU{lQhtk{w_nZ|Q4Vlui+L;GioShAUNLyjv4%uyn4WRu=j{y0@VC|PV^HMLlM z6RmKvfN!^vxmZ3%-4-HYE_;0c`gk5# zdqEZu+C}D8e+RE(+FEYB?G>D<8TM22nFDd{#NIjdZ~&HZR$+*LQ=yjoty0*7PD9T` z=eFe3br1}@Y=w2U!P242pYDLQa35uFEE2elIS_SAtQS3f&^bHp|F)0Ld04>*LPm-v zGqE)zG4gcnlc})%zNMx|nlk=vP$pq8sW6r0G)m*1QKNUp^*Gs*pKD>ZhGus1gA9W^ z_z+i&Rs7_rl0KTA^C8~AlS9ViHyeg-qhVKkE-EIvQA&h%&JQi5VHG#9zCke+xCHnO zRzbrD?4OH?{nDl$>f75X5F{q2OaIC9F3jbms={-OS1FCK)93Yzy%QmzBDyD{*nT^| zY?8<}_|Ll5pHf5$bp&2WysioV644xT_EU?!R!H!jD|%59mR!*K;Wu8Y-XPPd2YuPQSQ}0G;CzPnVAyT^14v ztA+_rZM!`@C~I?yk9$1VyQ{#t9tav-+Cf9g!4)E^7FU-JTyCN}TI|`2L%u&dh(S^+ z5+eC)AjhcIqVi%LEhWZwsiS?Af2M zJ=A*-p}wb0V|8xUn7!xk%=g?<4G@pr`Q|vSan?D&{?-uqB?x9Od0hP+q0nUL8z=|r z=LB%l%2$JeNgBb=-rsD|d$Md}RT1Txe%1~&8mVp`tQbO^9Y=79a`1gzuy*P~^&9fA z%{*-$>N7Jqs*w%PdDs~JE4w_1ELvA+GFS~l?RRWRCR1W|2El4|yt$|WSGMlvf6gu4 zc9hDmzK0;KNg2WUVRNnnnQBBCwL*T&WvH$LSz@ zYc`<23o!s{Y^>#vm(PpNmW~-Ezr66>Z;Zkk0L`rpF)X@juXCGEa(5zPQ%!;9drQmU zl;EV@XeM29p6N`RHEe6)1E(L<%-Rl`shYWy2IcX-hJ7%anhiQETGk=YeD4D9u(R0m z^{OYXfg6>Ua|jrxlsK(sPvHsbB3fFn<8V&i8v7}>F8jc`=Wju4*70)X6F;e!Wl$v! zM8l3yaGl$kn;RIU|9k~8CoC;x9V3L+m(L}Ppr}pg-0XJ$&8~Vjg=|P;Uei3oI~>Nb zW0`#T$-r;3Icf?*rAuzl)Z8HnqS$Wgw^@n?@iuYK%!m4C-o(~FBQ_J>i+J6CGL=Q0 zAAvZq=m{^R5RU&*5aD08x69q!LeBKl6UqYcNGev6j>bPY^S#rQIO3JdcZ(%TLz zQ>{~atU^8}Qp3iFimXQ`{sKI~J2wONZ;JY@8~AFvsw240Z?g2}OSIgJYpF{46~isJ zq`6eJ136iXv1sW!?A?RU(~nS~t9SP7QuJ?$D=oG@$Ns?3&UF8Q2aOpJ{CO^;{x|mT z$~C~PdMq3Q_uoJEY`0G($JiF0Zpe(#CEhWauPxsEq{|!-@yBr2x&86ke>uvy=A*pK z`KDMAk?PPauoR8V z=$S6Fg)d-_I;IE(j) zGrb!8CH=u_?dB34*`TXM*F88)<0!vM)a_k?A^55HAs>3qoyDa+@k``cnrOSnS)0bj zgF^swdG9sk{9s-i2EhmfxDUxpWC$vg3mDIXE_8J_*-wm;oWu4I1&ydO@$fBRVQ#E&#;{bMn@WcpMWNK6c%ty1T&Lm72hsQ0TPx6|7Dj4y5TUR zoB4{ceHf&L>-fy@X!~~x%bKONogZ%Kk_yNR1_u#0iItbKT2IvoLDwLZ!EV;F1YZtA zI9h>gs(_QS0a@LeRH#$W_$?wN%-Yw)_|nm?`|sQL1kUD7GX zy-?vU?a`m&J-4)2`_KCCmTfU`+&8TSpM^`@K;S|8?VxGd2P^-so5r)sdXM6`|D$sf z4dw}@=UvJ@@KRJW5FD-=G^UyU%1UjU$&hwUi}53~)N6I3Q#Zmg&<7F^j;q))9JqLzcJc5ET z! z7M>)$e+`iIRzt^~XPXa}CmQ5haS7hr%fWHDmV%_SIs(pmx7*8I-p~6ps;!Mrq^vZV z*+{`43dUxLU!UDCns1pzq}GP?GUb9h#NK5+z0HIlRVu zM0`z{tl;7uqu+tCBlkk~kN*L#P#%lZ--DLk8T#^PPZUsNdYiqruoR6rISF( zM=kuvAw6&$9a7`1Z}}n8-PEv?Xgx7aO7O!vSDY*5Bsi|}{?J*w zxz)fLazY~{!uAOASqq}kkVxHj^1ydSg{|)1^++9VSVr^vH=A!sIt&v&Ptn`2ecXdK zuH~GuEco#XUDFpZB_GF1vOA28+`GI!faxdC_Q2An3Y@=wkpL*fUBI@dpyv|lK_?=f zQ(dfkZ{JE_OcZu1Tcq%bBk~%8m>W_;V zq>W`45;P{D7>y3%-?S2T3(9@%VuYwx1A}NuFWeB!C%j+Y?iIKp2vs}F5CJU9vGwf2 zZH?$SNy(&H;F+js@^V+q#|BlU#_J&_r8Ib>RzL4PU3r!MwJKZ8I$#P|XcJ3IWQ8R6 z$J*RWY=w+J1A|_R?sDoYG-*N`K0Rlni2R+0bN=gJ{JxLeAIf3{Nv{b)%i)C*niI*7 zWAIt-8UK{Tcm@eE?_K1d)LW)+K4b{K_;^{V_q1gA3MQ@q#?f}3*As}pu6YXv!Mzub z$3TO8z;=e)U$jK2TMnuB`H-AB;@k@OvbS3T6}5u$Bj>n{l>1~mM7-F~AAv1zDG=YD z72$j%FrN&xOhV-IRAIu5yOaDImsY&mz2r(j5RZHqm&7yzJNyfCPraaOC!hP7Xn(^B zu@LOw%YNKx;Mz{H$218o8Sk6X$lClSyar$-c8Lw4Rt!6F$5qm9u7g0KtoXQPIPKG8 z-X8l#y_bk;DfUzceo664e)QobTk7Hg#Me9uR^g$mlsp5Gclx&MQ=#DixS7B8b(*|8 z#kvRSF5J=+z@qM3680UdfsW|7B)wuIMqAlKXm4jvfHS~+y zmgi!097jD-<%$z!=y7<+f@kRH`fbD=;~%E_k1|9&7JcCR>DgZhhF)IDEN5f`p+WO@ zZ?~YT%9w-0;cnJWd4w>^W&fXCo0~X0IG*UZP$NcAMW>(rY>_5Cnwm{b*JnZRSvtE|H64QHG_J*pv z2z5@Dlcq|q;`*|qQ&hn6p z0J5^{7^6Qo55LOKa4Ypb%P%bnQx&`bN#B7ew^rJR|4i11pJ#>W29vf6oW8hCxCUuG zcO<_%96gXDM0ntx^TZ02T%YuOL2b%7d{fO-Afk`_)P=LX$;>Am*9@`%!ypS_Iyqbj zO{TE(9F5i>4_U^{X}FA45k#$5y=@p8e&OOE7(0d4q-TMPz)Y|LZ|++aBy`5ei6 z>BP|8IHEc*3$$t^xBti4XnZ6*z?$ydK`aLquS~wQF>~cXzrbtz)4#!~@b+P#AbI#8 z1**-u8JER)fr8yP8LV8-U2d}L?2WHli>*U*E77xB_y#=U>0U1{u?;vMs!LN2EQeB| z{@zsqo0j=TL5*fR36G`gDzNzNzaJQpqHxU-hOpe>o%_f8;hg^LaZhepW)D6--INy<}EQ*KLuP_{3JMh{z_-I>=8(Ct=tY!mbS zaEj`@Ym24BNc$AT|kO0HPz}T))3!U5XX!*1RLsg2(ExB zR1>-%dF;7Vn0k<)>Ki=Vv~Qdk-KRtud{iTYA1Fet*Vf_k3I2phtn?Mc2x2yIc0BzI z0IqF7v0(A+O)BTQhC#3lrGjKXJ69zoOgo`A=ur!NI}U!or|*8!S1QdWoD+ z`m0oESU}uCp=0Fci?NmZ8A;I!7tSLQ_ji``$F5q*tH)H1%n(x6eAR!F3)w4{T?bBb z?jAD7^8J&Zxd`H*q!$&Io!xC+8yd$dyT3|)eoGfNd0N&y`8KO_eTy>3;--6TU)OxN zV)8OeV$9k;iI2cs+SRwWZmA$fVf^YRjG|fSKFJbI|DU>{DbF8CHMO-ge=}}9@z*#w z5NWSv?jLe>*}l;EsdA?jlv^5$C!b*77L>l1^;4fKRZaO-YKy*sOi4}FHK6bRvy)=* zGYh=?4=<3LT{3j5iSnLroHQ|s!zz-!51W2v{_8xx?glz*=tAv@a4~ZvgCd)>e`odv z_nLw8J)h*4CeU|<-GVv#`N?!EY8p}QT68woMQx9jRBbmUGg=wml50u@bIpEvaRhSg zQcIkbyF5^i@g9XO(_{_glVt*aGkhSv+D6pIzmA%0yEuPg#$&zE8bSCwz*GR$|kcRFBNO{VHnyo=Xx7xbVAXyONG1Opi9*Llwqx?$owrGy_E z5b<84onM&`> zXAZQqvZ~I^4H5j2x5Yai5-7#fFngp z{CnA|`89m@zQk_FOsBjbCSv3rcBU_E&~(_J;=tlefkCZ__3SuE8CadQIMeMxDi}0h zZCjigfst=Y>D?ayhBwO#RZjYhz^8e4*Q=(b4$a8M=FeKsOgr9d<|LPC`tp^!4Pz!% z&|~Et^h5}FG>iKxe|F@CkcQfRkT~ z>z0D3x@KYXw7YwIg++~XCmf1}CG|QEL$3A_RD(6I(CyJaKbagi48LCsjua0<(;6=B zsDS0qiMslT&F?PkQ72oez?=x6OGQsqa>6!F`R%24mxS700%-5ZY`#BCeDo}uX7iEx zFe$wd)+^A&l=?E6OW-Bz#le7N#XEx6=;dd*6h!JN(+^ha?~Qi-A6ff0Wv<_fkj(tU zYg>3NI6!GgEqagX&?c>{>#UvfWyC6- zB7R!+D)Wrm>3}^_hmTn9j1u|YM7vYt$3tHHe6f-BELzN0@j9UeP$TVuXc%&~PA+Qg zD~g1^-E{3nR<6IRyCX(Q$(RsR-Yjj4<7=kgymosNcli?d_Ag|jvL}IY8o>yi9o8Tb zZ#_ZLe6Q+WrsPUx5x)^@alEs6jj`-rs%ApeeXnY6MU2+(+cZdD#IPe0kbkT`$&lTQUK4(;7 zBN~=)oqdeghK<>4$>_+)6W~tQ&%_ud>@%K$1NSsxyJ!z;JXj@^rm9{r(cYT`LGIO0 zWZs^J^fRs}D3zspu;z`u5u8&t@M?n(_Y-^?`xwPHZc;(gT9ODGWvgm+FQsXwV4S#L(T{`$kO%kOk+ciQ-KT@&hl27I7-_^UB~ClaK3~l_#`?I+3D_AAbDQyy7Sv9LRm9xXw*y zY46AY23`2&AFMERP=y+5chYABUMM=fW_n$di^L611}1&pmHejP;pBsnDTr1ywIWU~ zUm+@BV3XGo-_}fHiS%CKq5j?drm)Ys6~tqe5kM8YmIb|r(+Hn7m$081tvg zMA=VBu_z!1tUJhXuV}t<6OeHngMR3EL|mbMy(-%&Kj>#zod4k+kPNtB6Dqu#{!J}C z(1nQB;iKeF#d&;Tc?rBk;9>n-QC%<-vWkgGPx_~PM6nyFHsRTJ9lf^%knUJMt{42S zP5`^h;X+E5O=#HSF3>YA@+}}tiOo{~3%RM5wOH`6)=6BlaW4q&eMuVxqxC4@6fBl{ zh%7ASJx+f|V5ZD(!WF;iarg@!$mbotk|dIGXQ&J9bLn!hRGt}mSpb}(o)+I~cvr53 zU)qIkF+{<@UE-P20n%WjNFGpzjVCrMaXTWFM zYuFRa5K3x?2gB}9=&%lnR}H4IABr+a>KZVIY*D*@^E+)0_{;ATd#C`#{{k1LnoC!! z5H;YZ`Mi$puvi@#CO^1k6!QCUy=suP4q3)(S9um-`N9qPRs7$5tcxtRo@+#NI}M6# z-Glf`z(3o*js7m4Zn?Ij-ZBk23CntzKjNpj`+1$_l{|(ffTlkB?}0U2D!A+)$p9zr z-R4{!^2u}uaaYz5m*rgG+U<`5C^~HAklH8CJ<)GkdZ`Xa<%-`}qIA@{*;1+E*M@I% z0ryYmZUKLqwS|YiJ(^i$Wa4qY;5}P?a);qj5n=rX&q zVqu9b&1Koh2#PDdT_{vALlxmA?rn9sjQjO|c-${*b`~A+J7k1#Y5P`JriwhPr4u@6 ztK)MwdjljoG}qqPn2bcPv}=htzat5ukT+@mwV4;Vc5j)DddhU6?B`E`M-1o0ZKM!R zg21rgjGVHe1=r{UY;0`Fh`Wauvxig`&xn$257Fk0eG@5>Cc5)$wnC_k*9m)O0`C0MfXI@_Z!uE_gT+Q`c zDS{w5IqKOP)niEX+2sxOz)jX_*zWhczZhq?K3{%}T2B)3f0kqZ45USh4cE5~y{UHZ zcUK&cHuff!lPo%$IAkhro@I%@nP}^Ie)78b&C{93yys!!{R)~6?hWE%kddi{TGe6gRFwb6qa z)*&|qrzxj?=e{m~=S+>r3Roq-S1fAvm{N&{=!I~!Y>uJ+Po0&(Q=pXw2RZth^2;gP zKJlSCbn4G^HN!+TQ?X9vLEtdNu!2M3ZB6Efi`lT&embAG#vJG#8acrr`rOZgLiur$ zlr=jbwQ)2vw(}yn`A=Pi5wG)EnuFoKFGqa&*S}OBdYRPU%Ln-Of!pIm7?<6%@hQP+ z@z!U8JbrX27UHx4q|1EO2zrQ!)8DN2rBP-3W0C$_Q&%VKT}jaEUyemEs5XP?7Q&HC`}_5(KcuRgwS>Vrd5yy z^FRbGAevD6JCFaV=}dI)d&6aus4Qsj^3}A4U(Qu;3z1Ey^P30N^W>iwnd1~*V$b%3 z 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 diff --git a/misc/logos/misc.go b/misc/logos/misc.go deleted file mode 100644 index 4bf3c8c6267a..000000000000 --- a/misc/logos/misc.go +++ /dev/null @@ -1,155 +0,0 @@ -package logos - -import ( - "strings" - "unicode" - - "github.com/gdamore/tcell/v2" - runewidth "github.com/mattn/go-runewidth" -) - -// splits a string into lines by newline. -func splitLines(s string) (ss []string) { - return strings.Split(s, "\n") -} - -// splits a string according to unicode spaces. -func splitSpaces(s string) (ss []string) { - buf := []rune{} - for _, r := range s { - if unicode.IsSpace(r) { - // continue - if len(buf) > 0 { - ss = append(ss, string(buf)) - buf = nil - } - } else { - buf = append(buf, r) - } - } - if len(buf) > 0 { - ss = append(ss, string(buf)) - // buf = nil - } - return ss -} - -func toRunes(s string) []rune { - runes := make([]rune, 0, len(s)) - for _, r := range s { - runes = append(runes, r) - } - return runes -} - -// gets the terminal display width of a string. -// must be compatible with nextCharacter(). -// NOTE: must be kept in sync with nextCharacter(); see tests. -func widthOf(s string) (l int) { - zwj := false // zero width joiner '\u200d'. - for _, r := range s { - if r == '\u200d' { - zwj = true - continue - } - if zwj { - zwj = false - continue - } - switch runewidth.RuneWidth(r) { - case 0: - if isCombining(r) { - // combining characters have no length. - } else { - l++ // show a blank instead, weird. - } - case 1: - l++ - case 2: - l += 2 - default: - panic("should not happen") - } - } - return l -} - -// given runes of a valid utf8 string, -// return a string that represents -// the next single character (with any modifiers). -// w: width of character. n: number of runes read -func nextCharacter(rz []rune) (s string, w int, n int) { - for n = 0; n < len(rz); n++ { - r := rz[n] - if r == '\u200d' { - // special case: zero width joins. - s = s + string(r) - if n+1 < len(rz) { - s = s + string(rz[n+1]) - n++ - continue - } else { - // just continue, return invalid string s. - n++ - return - } - } else if 0 < len(s) { - return - } else { - // append r to s and inc w. - rw := runewidth.RuneWidth(r) - s = s + string(r) - if rw == 0 { - if isCombining(r) { - // no width - } else { - w += 1 - } - } else { - w += rw - } - } - } - return -} - -//---------------------------------------- - -func AbsCoord(elem Elem) (crd Coord) { - for elem != nil { - crd = crd.Add(elem.GetCoord()) - elem = elem.GetParent() - } - return -} - -var randColors []Color = []Color{ - tcell.ColorAliceBlue, - tcell.ColorAntiqueWhite, - tcell.ColorAquaMarine, - tcell.ColorAzure, - tcell.ColorBeige, - tcell.ColorBisque, - tcell.ColorBlanchedAlmond, - tcell.ColorBlueViolet, - tcell.ColorBrown, - tcell.ColorBurlyWood, -} - -var rctr = 0 - -func RandColor() Color { - rctr++ - return randColors[rctr%len(randColors)] -} - -func IsInBounds(x, y int, origin Coord, size Size) bool { - if x < origin.X || y < origin.Y { - return false - } - if origin.X+size.Width <= x || - origin.Y+size.Height <= y { - return false - } - return true -} diff --git a/misc/logos/misc_test.go b/misc/logos/misc_test.go deleted file mode 100644 index a147f8b41ea7..000000000000 --- a/misc/logos/misc_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package logos - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/gnolang/gno/tm2/pkg/random" -) - -// Tests whether widthOf() and nextCharacter() do the same thing. -func TestStringWidthSlow(t *testing.T) { - t.Skip("test failing") - for n := 1; n < 4; n++ { - bz := make([]byte, n) - for { - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - if width1 == 0 { - if isRepeatedWZJ(bz) { - // these bytes encode one or more U+200D WZJ as UTF8. - } else { - require.Fail(t, fmt.Sprintf("unexpected zero width string for bytes %X", bz)) - } - } else { - require.True(t, 0 < width1, "got zero width for bytes %X", bz) - } - require.Equal(t, width1, width2) - if !incBuffer(bz) { - break - } - } - } -} - -// Same as above but for longer pseudo-random strings. -func TestStringWidthRandom(t *testing.T) { - max := 10 * 1024 * 1024 - for i := 0; i < max; i++ { - if i%(max/80) == 0 { - fmt.Print(".") - } - bz := random.RandBytes(12) - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - if width1 == 0 { - if isRepeatedWZJ(bz) { - // these bytes encode one or more U+200D WZJ as UTF8. - } else { - require.Fail(t, "unexpected zero width string") - } - } else { - require.True(t, 0 < width1, "got zero width for bytes %X", bz) - } - require.Equal(t, width1, width2, - "want %d but got %d the slow way: %X", - width1, width2, bz) - } -} - -// For debugging. -func TestStringWidthDummy(t *testing.T) { - bz := []byte{0x0C, 0x5B, 0x0D, 0xCF, 0xC5, 0xE2, 0x80, 0x8D, 0xC1, 0x32, 0x69, 0x41} - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - if width1 == 0 { - if isRepeatedWZJ(bz) { - // these bytes encode one or more U+200D WZJ as UTF8. - } else { - require.Fail(t, "unexpected zero width string") - } - } else { - require.True(t, 0 < width1, "got zero width for bytes %X", bz) - } - require.Equal(t, width1, width2, - "want %d but got %d the slow way: %X", - width1, width2, bz) -} - -// For debugging. -func TestStringWidthDummy2(t *testing.T) { - t.Skip("test failing") - // NOTE: this is broken in the OSX terminal. This should print a USA flag - // and have width 2, or possibly default to two block letters "U" and "S", - // but my terminal prints a flag of width 1. - bz := []byte("\U0001f1fa\U0001f1f8") - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - require.Equal(t, 1, width1) - require.Equal(t, width1, width2, - "want %d but got %d the slow way: %X", - width1, width2, bz) -} - -func isRepeatedWZJ(bz []byte) bool { - if len(bz)%3 != 0 { - return false - } - // this is U+200D is UTF8. - for i := 0; i < len(bz); i += 3 { - if bz[i] != 0xE2 { - return false - } - if bz[i+1] != 0x80 { - return false - } - if bz[i+2] != 0x8D { - return false - } - } - return true -} - -// get the width of a string using nextCharacter(). -func widthOfSlow(s string) (w int) { - rz := toRunes(s) - for 0 < len(rz) { - _, w2, n := nextCharacter(rz) - if n == 0 { - panic("should not happen") - } - w += w2 - rz = rz[n:] - } - return -} - -//---------------------------------------- -// incBuffer for testing - -// If overflow, bz becomes zero and returns false. -func incBuffer(bz []byte) bool { - for i := 0; i < len(bz); i++ { - if bz[i] == 0xFF { - bz[i] = 0x00 - } else { - bz[i]++ - return true - } - } - return false -} - -func TestIncBuffer1(t *testing.T) { - bz := []byte{0x00} - for i := 0; i < (1<<(1*8))-1; i++ { - require.Equal(t, true, incBuffer(bz)) - require.Equal(t, byte(i+1), bz[0]) - } - require.Equal(t, false, incBuffer(bz)) - require.Equal(t, byte(0x00), bz[0]) -} - -func TestIncBuffer2(t *testing.T) { - bz := []byte{0x00, 0x00} - for i := 0; i < (1<<(2*8))-1; i++ { - require.Equal(t, true, incBuffer(bz)) - require.Equal(t, byte(((i+1)>>0)%256), bz[0]) - require.Equal(t, byte(((i+1)>>8)%256), bz[1]) - } - require.Equal(t, []byte{0xFF, 0xFF}, bz) - require.Equal(t, false, incBuffer(bz)) - require.Equal(t, byte(0x00), bz[0]) - require.Equal(t, byte(0x00), bz[1]) -} diff --git a/misc/logos/stack.go b/misc/logos/stack.go deleted file mode 100644 index 17b18327fd2e..000000000000 --- a/misc/logos/stack.go +++ /dev/null @@ -1,160 +0,0 @@ -package logos - -import ( - "fmt" - "strings" - - "github.com/gdamore/tcell/v2" -) - -//---------------------------------------- -// Stack - -// A Stack is like a Page, but it only highlights the top -// element, and dims, occludes, or hides lower elements. A -// Stack is therefore ideal for showing modal views. NOTE: -// While most applications shouldn't, it's perfectly fine to -// embed Stacks within Stacks, or layer them on top within a -// stack. -type Stack struct { - Page // a Stack has the same fields as a page. -} - -func NewStack(size Size) *Stack { - return &Stack{ - Page: Page{ - Size: size, // dontcare. - Elems: nil, // nil layers. - Cursor: -1, - }, - } -} - -func (st *Stack) StringIndented(indent string) string { - elines := []string{} - eindent := indent + " " - for _, elem := range st.Elems { - elines = append(elines, eindent+elem.StringIndented(eindent)) - } - return fmt.Sprintf("Stack%v@%p\n%s", - st.Size, - st, - strings.Join(elines, "\n")) -} - -func (st *Stack) String() string { - return fmt.Sprintf("Stack%v{%d}@%p", - st.Size, - len(st.Elems), - st) -} - -func (st *Stack) PushLayer(layer Elem) { - layer.SetParent(st) - st.Elems = append(st.Elems, layer) - st.Cursor++ - st.SetIsDirty(true) -} - -// A Stack's size is simply determined by its .Size. -func (st *Stack) Measure() Size { - return st.Size -} - -// A Stack's render function behaves the same as a Page's; -// it renders its elements (here, its layers). -func (st *Stack) Render() (updated bool) { - return st.Page.Render() -} - -// Draw the rendered layers onto the view. Any dimming of -// occluded layers must actually stretch in all directions -// infinitely (since we can scroll beyond the bounds of any -// view and we expect the dimming effect to carry while we -// scroll), so the entire view is dimmed first, and then the -// upper-most layer is drawn. -func (st *Stack) Draw(offset Coord, view View) { - // Draw bottom layers. - if 1 < len(st.Elems) { - for _, elem := range st.Elems[:len(st.Elems)-1] { - loffset := offset.Sub(elem.GetCoord()) - elem.Draw(loffset, view) - } - } - if 0 < len(st.Elems) { - last := st.Elems[len(st.Elems)-1] - loffset := offset.Sub(last.GetCoord()) - // Draw occlusion screen on view. - for y := 0; y < view.Bounds.Height; y++ { - for x := 0; x < view.Bounds.Width; x++ { - vcell := view.GetCell(x, y) - inBounds := IsInBounds(x, y, - loffset.Neg(), - last.GetSize()) - if inBounds { - // Reset unsets residual "occluded", - // "cursor", and other attributes from the - // previous layer which are no longer - // relevant. - vcell.Reset() - } else { - vcell.SetIsOccluded(true) - } - } - } - // Draw last (top) layer. - last.Draw(loffset, view) - } else { - // Draw occlusion screen on view. - for y := 0; y < view.Bounds.Height; y++ { - for x := 0; x < view.Bounds.Width; x++ { - vcell := view.GetCell(x, y) - vcell.SetIsOccluded(true) - } - } - } -} - -func (st *Stack) ProcessEventKey(ev *EventKey) bool { - // An empty *Stack is inert. - if len(st.Page.Elems) == 0 { - return false - } - // Try to let the last layer handle it. - last := st.Page.Elems[len(st.Page.Elems)-1] - if last.ProcessEventKey(ev) { - return true - } - // Maybe it's something for the stack. - switch ev.Key() { - case tcell.KeyEsc: - if 1 < len(st.Page.Elems) { - // Pop the last layer. - st.Elems = st.Elems[:len(st.Elems)-1] - st.Cursor-- - st.SetIsDirty(true) - return true - } else { - // Let the last layer stick around. - return false - } - default: - return false - } -} - -// Traverses the inclusive ancestors of elem and returns the -// first *Stack encountered. The purpose of this function is -// to find where to push new layers and modal elements for -// drawing. -func StackOf(elem Elem) *Stack { - for elem != nil { - fmt.Println("StackOf", elem) - if st, ok := elem.(*Stack); ok { - return st - } else { - elem = elem.GetParent() - } - } - return nil // no stack -} diff --git a/misc/logos/types.go b/misc/logos/types.go deleted file mode 100644 index 96e983992eb1..000000000000 --- a/misc/logos/types.go +++ /dev/null @@ -1,1006 +0,0 @@ -package logos - -import ( - "fmt" - "strings" - - "github.com/gdamore/tcell/v2" -) - -// ---------------------------------------- -// Page - -// A Page has renderable Elem(ents). -type Page struct { - Coord // used by parent only. TODO document. - Size - *Style - Attrs - Elems []Elem - Cursor int // selected cursor element index, or -1. -} - -// An elem is something that can draw a portion of itself onto -// a view. It has a relative coord and a size. Before it is -// drawn, it is rendered. Measure will update its size, while -// GetSize() returns the cached size. ProcessEventKey() -// returns true if event was consumed. -type Elem interface { - GetParent() Elem - SetParent(Elem) - GetCoord() Coord - SetCoord(Coord) - GetStyle() *Style - SetStyle(*Style) - GetAttrs() *Attrs - GetIsCursor() bool - SetIsCursor(bool) - GetIsDirty() bool - SetIsDirty(bool) - GetIsOccluded() bool - SetIsOccluded(bool) - GetSize() Size - Measure() Size - Render() bool - Draw(offset Coord, dst View) - ProcessEventKey(*EventKey) bool - String() string - StringIndented(indent string) string - // NOTE: SetSize(Size) isn't an elem interface, as - // containers in general can't force elements to be of a - // certain size, but rather prefers drawing out of - // bounds; this opinion may distinguishes Logos from - // other most gui frameworks. -} - -var ( - _ Elem = &Page{} - _ Elem = &BufferedElemView{} - _ Elem = &TextElem{} - _ Elem = &Stack{} -) - -// produces a page from a string. -// width is the width of the page. -// if isCode, width is ignored. -func NewPage(s string, width int, isCode bool, style *Style) *Page { - page := &Page{ - Size: Size{ - Width: width, - Height: -1, // not set - }, - Style: style, - Elems: nil, // will set - Cursor: -1, - } - elems := []Elem{} - if s != "" { - pad := style.GetPadding() - ypos := 0 + pad.Top - xpos := 0 + pad.Left - lines := splitLines(s) - if isCode { - for _, line := range lines { - te := NewTextElem(line, style) - te.SetParent(page) - te.SetCoord(Coord{X: xpos, Y: ypos}) - elems = append(elems, te) - ypos++ - xpos = 0 + pad.Left - } - } else { - for _, line := range lines { - words := splitSpaces(line) - for _, word := range words { - wd := widthOf(word) - if width < xpos+wd+pad.Left+pad.Right { - if xpos != 0+pad.Left { - ypos++ - xpos = 0 + pad.Left - } - } - te := NewTextElem(word, style) - te.SetParent(page) - te.SetCoord(Coord{X: xpos, Y: ypos}) - elems = append(elems, te) - xpos += te.Width // size of word - xpos += 1 // space after each word (not written) - } - ypos++ - xpos = 0 + pad.Left - } - } - } - page.Elems = elems - page.Measure() - page.SetIsDirty(true) - return page -} - -func (pg *Page) StringIndented(indent string) string { - elines := []string{} - eindent := indent + " " - for _, elem := range pg.Elems { - elines = append(elines, eindent+elem.StringIndented(eindent)) - } - return fmt.Sprintf("Page%v@%p\n%s", - pg.Size, - pg, - strings.Join(elines, "\n")) -} - -func (pg *Page) String() string { - return fmt.Sprintf("Page%v{%d}@%p", - pg.Size, len(pg.Elems), pg) -} - -func (pg *Page) NextCoord() Coord { - if len(pg.Elems) == 0 { - return Coord{X: pg.GetPadding().Left, Y: pg.GetPadding().Top} - } else { - last := pg.Elems[len(pg.Elems)-1] - last.Measure() - lcoord := last.GetCoord() - lsize := last.GetSize() - return Coord{ - X: pg.GetPadding().Left, - Y: lcoord.Y + lsize.Height, // no spacers by spec. - } - } -} - -func (pg *Page) SetStyle(style *Style) { - pg.Style = style -} - -// Measures the size of elem and appends to page below the last element, -// or if empty, the top-leftmost coordinate exclusive of padding cells. -func (pg *Page) AppendElem(elem Elem) { - ncoord := pg.NextCoord() - elem.SetParent(pg) - elem.SetCoord(ncoord) - pg.Elems = append(pg.Elems, elem) - pg.SetIsDirty(true) -} - -// Assumes page starts at 0,0. -func (pg *Page) Measure() Size { - pad := pg.GetPadding() - maxX := pad.Left - maxY := pad.Top - for _, view := range pg.Elems { - coord := view.GetCoord() - size := view.GetSize() - if maxX < coord.X+size.Width { - maxX = coord.X + size.Width - } - if maxY < coord.Y+size.Height { - maxY = coord.Y + size.Height - } - } - size := Size{ - Width: maxX + pad.Right, - Height: maxY + pad.Bottom, - } - pg.Size = size - return size -} - -/* - Page draw logic: - Let's say we want to draw a Page. We want to draw it onto - some buffer, or more specially some "view" of a buffer (as - a slice of an array is a view into an array buffer). - - Page virtual bounds: - 0 - - - - - - - - - - + - :\ : - : \ (3,3) : - : @-----------+ : - : |View | : - : | | : - : +-----------+ : - : : - + - - - - - - - - - - + - - 0 is the origin point for the Page. - @ is an offset within the page. @ here is (3,3). - It is where the View is conceptually placed, but - otherwise the View isn't aware where @ is. - This offset is passed in as an argument 'offset'. - - NOTE: Offset is relative in the base page. To offset the - drawing position in the view (e.g. to only write on the - right half of the buffer view), derive another view from - the original. - - The View is associated with an underlying (base) buffer. - - Page virtual bounds: - 0 - - - - - - - - - - + - +=:=====================:===+ <-- underlying Buffer - | : : | - | : @-------------+ : | - | : |View | : | - | : |.Offset=(5,2)| : | - | : +-------------+ : | - | : : | - | + - - - - - - - - - - + | - +===========================+ - - Each element must be drawn onto the buffer view with the - right offset algebra applied. Here is a related diagram - showing the buffer in relation to page elements. - - Page virtual bounds: - 0 - - - - - - - - - - - + - :elem 1 |elem 2 : - : @------------+ : - : |View | : - + - - - | - E - - - -|- + - :elem 3 | |elem 4 | : - : +------------+ : - : | : - + - - - - - - - - - - - + - - In this example the page is composed of four element tiles. - E is elem-4's offset relative to 0, the page's origin. To - draw the top-left portion of elem-4 onto the buffer slice - as shown, the element is drawn with an offset of @-E, which - is negative and indicates that the element should be drawn - offset positively (right and bottom) from @. -*/ - -// Unlike TextElem or BufferedElemView, a Page doesn't keep -// its own buffer. Its render function calls the elements' -// render functions, and the element buffers are combined -// during Draw(). There is a need for distinction because -// Draw() can't be too slow, so Render() is about optimizing -// Draw() calls. The distinction between *Page and -// BufferedElemView gives the user more flexibility. -func (pg *Page) Render() (updated bool) { - if !pg.GetIsDirty() { - return - } else { - defer pg.SetIsDirty(false) - } - for _, elem := range pg.Elems { - elem.Render() - } - return true -} - -// Draw the rendered page elements onto the view. -func (pg *Page) Draw(offset Coord, view View) { - style := pg.GetStyle() - border := style.GetBorder() - minX, maxX, minY, maxY := computeIntersection(pg.Size, offset, view.Bounds) - // First, draw page background style. - for y := minY; y < maxY; y++ { - for x := minX; x < maxX; x++ { - xo, yo := x-offset.X, y-offset.Y - vcell := view.GetCell(xo, yo) - // Draw area and border. - if x == 0 { - if y == pg.Size.Height-1 { - // handle this case first so if height is 1, - // this corner is preferred. - vcell.SetValue(border.BLCorner(), 1, style, pg) - } else if y == 0 { - vcell.SetValue(border.TLCorner(), 1, style, pg) - } else { - vcell.SetValue(border.LeftBorder(y), 1, style, pg) - } - } else if x == pg.Size.Width-1 { - if y == pg.Size.Height-1 { - // ditto for future left-right language support. - vcell.SetValue(border.BRCorner(), 1, style, pg) - } else if y == 0 { - vcell.SetValue(border.TRCorner(), 1, style, pg) - } else { - vcell.SetValue(border.RightBorder(y), 1, style, pg) - } - } else if y == 0 { - vcell.SetValue(border.TopBorder(x), 1, style, pg) - } else if y == pg.Size.Height-1 { - vcell.SetValue(border.BottomBorder(x), 1, style, pg) - } else { // Draw area. - vcell.SetValue(" ", 1, style, pg) - } - } - } - // Then, draw elems. - for _, elem := range pg.Elems { - eoffset := offset.Sub(elem.GetCoord()) - elem.Draw(eoffset, view) - } -} - -type EventKey = tcell.EventKey - -func (pg *Page) ProcessEventKey(ev *EventKey) bool { - switch ev.Key() { - case tcell.KeyEsc: - return false - case tcell.KeyUp: - pg.DecCursor(true) - case tcell.KeyDown: - pg.IncCursor(true) - case tcell.KeyLeft: - pg.DecCursor(false) - case tcell.KeyRight: - pg.IncCursor(false) - case tcell.KeyEnter: - if pg.Cursor == -1 { - // as if pressed down - pg.IncCursor(true) - return true - } - // XXX this is a test. - st := StackOf(pg) - celem := pg.Elems[pg.Cursor] - coord := AbsCoord(celem).Sub(AbsCoord(st)) - page := NewPage("this is a test", 80, false, pg.Style) - coord.Y += 1 - coord.X += 2 - page.SetCoord(coord) - st.PushLayer(page) - default: - return false - } - // Leave as true for convenience in cases above. - // If a key event wasn't consumed, return false. - return true -} - -func (pg *Page) IncCursor(isVertical bool) { - if pg.Cursor == -1 { - if len(pg.Elems) == 0 { - // nothing to select. - } else { - pg.Cursor = 0 - pg.Elems[pg.Cursor].SetIsCursor(true) - } - } else { - pg.Elems[pg.Cursor].SetIsCursor(false) - pg.Cursor++ - if pg.Cursor == len(pg.Elems) { - pg.Cursor = 0 // roll back. - } - pg.Elems[pg.Cursor].SetIsCursor(true) - } -} - -func (pg *Page) DecCursor(isVertical bool) { - if pg.Cursor == -1 { - if len(pg.Elems) == 0 { - // nothing to select. - } else { - pg.Cursor = len(pg.Elems) - 1 - pg.Elems[pg.Cursor].SetIsCursor(true) - } - } else { - pg.Elems[pg.Cursor].SetIsCursor(false) - pg.Cursor-- - if pg.Cursor == -1 { - pg.Cursor = len(pg.Elems) - 1 // roll forward. - } - pg.Elems[pg.Cursor].SetIsCursor(true) - } -} - -// ---------------------------------------- -// TextElem - -type TextElem struct { - Coord - Size - *Style // ignores padding. - Attrs - Text string - *Buffer -} - -func NewTextElem(text string, style *Style) *TextElem { - te := &TextElem{ - Style: style, - Text: text, - Buffer: NewBuffer(Size{ - Height: 1, - Width: widthOf(text), - }), - } - te.Measure() - te.SetIsDirty(true) - return te -} - -func (tel *TextElem) SetStyle(style *Style) { - tel.Style = style -} - -func (tel *TextElem) StringIndented(indent string) string { - return tel.String() -} - -func (tel *TextElem) String() string { - return fmt.Sprintf("Text{%q}", tel.Text) -} - -func (tel *TextElem) Measure() Size { - size := Size{ - Height: 1, - Width: widthOf(tel.Text), - } - tel.Size = size - return size -} - -func (tel *TextElem) Render() (updated bool) { - if tel.Height != 1 { - panic("should not happen") - } - if !tel.GetIsDirty() { - return - } else { - defer tel.SetIsDirty(false) - } - tel.Buffer.Reset() - style := tel.GetStyle() - runes := toRunes(tel.Text) - i := 0 - for 0 < len(runes) { - s, w, n := nextCharacter(runes) - if n == 0 { - panic(fmt.Sprintf( - "unexpected error reading next character from runes %v", - runes)) - } else { - runes = runes[n:] - } - cell := tel.Buffer.GetCell(i, 0) - cell.SetValue(s, w, style, tel) - for j := 1; j < w; j++ { - cell := tel.Buffer.GetCell(i+j, 0) - cell.SetValue("", 0, style, tel) // clear next cells - } - i += w - } - if i != tel.Buffer.Width { - panic(fmt.Sprintf( - "wrote %d cells but there are %d in buffer with text %q", - i, tel.Buffer.Width, tel.Text)) - } - return true -} - -func (tel *TextElem) Draw(offset Coord, view View) { - minX, maxX, minY, maxY := computeIntersection(tel.Size, offset, view.Bounds) - for y := minY; y < maxY; y++ { - if minY != 0 { - panic("should not happen") - } - for x := minX; x < maxX; x++ { - bcell := tel.Buffer.GetCell(x, y) - vcell := view.GetCell(x-offset.X, y-offset.Y) - vcell.SetValueFromCell(bcell) - } - } -} - -func (tel *TextElem) ProcessEventKey(ev *EventKey) bool { - return false // TODO: clipboard. -} - -// ---------------------------------------- -// misc. - -type Color = tcell.Color - -// Style is purely visual and has no side effects. -// It is generally referred to by pointer; you may need to copy before -// modifying. -type Style struct { - Foreground Color - Background Color - Padding Padding - Border Border - StyleFlags - Other []KVPair - CursorStyle *Style -} - -func DefaultStyle() *Style { - return &Style{ - Foreground: gDefaultForeground, - Background: gDefaultBackground, - CursorStyle: &Style{ - Background: tcell.ColorYellow, - }, - } -} - -var ( - gDefaultStyle = DefaultStyle() - gDefaultForeground = tcell.ColorBlack - gDefaultBackground = tcell.ColorLightBlue -) - -func (st *Style) Copy() *Style { - st2 := *st - return &st2 -} - -func (st *Style) GetStyle() *Style { - return st -} - -func (st *Style) GetForeground() Color { - if st == nil { - return gDefaultStyle.Foreground - } else { - return st.Foreground - } -} - -func (st *Style) GetBackground() Color { - if st == nil { - return gDefaultStyle.Background - } else { - return st.Background - } -} - -func (st *Style) GetPadding() Padding { - if st == nil { - return gDefaultStyle.Padding - } else { - return st.Padding - } -} - -func (st *Style) GetBorder() *Border { - if st == nil { - return &gDefaultStyle.Border - } else { - return &st.Border - } -} - -func (st *Style) GetCursorStyle() *Style { - if st == nil { - return gDefaultStyle.CursorStyle - } else if st.CursorStyle == nil { - return st - } else { - return st.CursorStyle - } -} - -// NOTE: this should only be called during the last step when -// writing to screen. The receiver must not be nil and must -// not be modified, and the result is a value, not the style -// of any particular element. -func (st *Style) WithAttrs(attrs *Attrs) (res Style) { - if st == nil { - panic("unexpected nil style") - } - if attrs.GetIsCursor() { - res = *st.GetCursorStyle() - } else { - res = *st - } - if attrs.GetIsOccluded() { - res.SetIsShaded(true) - } - return -} - -func (st Style) GetTStyle() (tst tcell.Style) { - if st.Foreground.Valid() { - tst = tst.Foreground(st.Foreground) - } else { - tst = tst.Foreground(gDefaultForeground) - } - if st.Background.Valid() { - tst = tst.Background(st.Background) - } else { - tst = tst.Background(gDefaultBackground) - } - if st.GetIsShaded() { - tst = tst.Dim(true) - tst = tst.Background(tcell.ColorGray) - } - // TODO StyleFlags - return tst -} - -type StyleFlags uint32 - -func (sf StyleFlags) GetIsDim() bool { - return (sf & StyleFlagDim) != 0 -} - -func (sf *StyleFlags) SetIsDim(id bool) { - if id { - *sf |= StyleFlagDim - } else { - *sf &= ^StyleFlagDim - } -} - -func (sf StyleFlags) GetIsShaded() bool { - return (sf & StyleFlagShaded) != 0 -} - -func (sf *StyleFlags) SetIsShaded(id bool) { - if id { - *sf |= StyleFlagShaded - } else { - *sf &= ^StyleFlagShaded - } -} - -const StyleFlagNone StyleFlags = 0 - -const ( - StyleFlagBold StyleFlags = 1 << iota - StyleFlagDim - StyleFlagShaded - StyleFlagBlink - StyleFlagUnderline - StyleFlagItalic - StyleFlagStrikeThrough -) - -// Attrs have side effects in the Logos system; -// for example, the lone cursor element (one with AttrFlagIsCursor set) -// is where most key events are sent to. -type Attrs struct { - Parent Elem - AttrFlags - Other []KVPair -} - -func (tt *Attrs) GetAttrs() *Attrs { - return tt -} - -func (tt *Attrs) GetParent() Elem { - return tt.Parent -} - -func (tt *Attrs) SetParent(p Elem) { - if tt.Parent != nil && tt.Parent != p { - panic("parent already set") - } - tt.Parent = p -} - -func (tt *Attrs) GetIsCursor() bool { - return (tt.AttrFlags & AttrFlagIsCursor) != 0 -} - -func (tt *Attrs) SetIsCursor(ic bool) { - if ic { - tt.AttrFlags |= AttrFlagIsCursor - } else { - tt.AttrFlags &= ^AttrFlagIsCursor - } - tt.SetIsDirty(true) -} - -func (tt *Attrs) GetIsDirty() bool { - return (tt.AttrFlags & AttrFlagIsDirty) != 0 -} - -func (tt *Attrs) SetIsDirty(id bool) { - if id { - tt.AttrFlags |= AttrFlagIsDirty - if tt.Parent != nil { - tt.Parent.SetIsDirty(true) - } - } else { - tt.AttrFlags &= ^AttrFlagIsDirty - } -} - -func (tt *Attrs) GetIsOccluded() bool { - return (tt.AttrFlags & AttrFlagIsOccluded) != 0 -} - -func (tt *Attrs) SetIsOccluded(ic bool) { - if ic { - tt.AttrFlags |= AttrFlagIsOccluded - } else { - tt.AttrFlags &= ^AttrFlagIsOccluded - } - tt.SetIsDirty(true) -} - -func (tt *Attrs) Merge(ot *Attrs) { - if ot.Parent != nil { - tt.Parent = ot.Parent - } - tt.AttrFlags |= ot.AttrFlags - tt.Other = ot.Other // TODO merge by key. -} - -// ---------------------------------------- -// AttrFlags - -// NOTE: AttrFlags are merged with a simple or-assign op. -type AttrFlags uint32 - -func (af AttrFlags) GetAttrFlags() AttrFlags { - return af -} - -const AttrFlagNone AttrFlags = 0 - -const ( - AttrFlagIsCursor AttrFlags = 1 << iota // is current cursor - AttrFlagIsSelected // is selected (among possibly others) - AttrFlagIsOccluded // is hidden due to stack - AttrFlagIsDirty // is dirty (not yet used) -) - -type KVPair struct { - Key string - Value interface{} -} - -// ---------------------------------------- -// computeIntersection() - -// els: element size -// elo: offset within element -// vws: view size -// minX,maxX,minY,maxY are relative to el. -// maxX and maxY are exclusive. -func computeIntersection(els Size, elo Coord, vws Size) (minX, maxX, minY, maxY int) { - if elo.X < 0 { - /* - View - +----------+ - | [Elem__|____] - +----------+ - x 0 - */ - minX = 0 - } else { - /* - View - +----------+ - [____|__Elem] | - +----------+ - 0 x - */ - minX = elo.X - } - if els.Width <= vws.Width+elo.X { - /* - View - +----------+ - [____|__Elem] | - +----------+ - W w+x - */ - maxX = els.Width - } else { - /* - View - +----------+ - | [Elem__|____] - +----------+ - w+x W - */ - maxX = vws.Width + elo.X - } - if elo.Y < 0 { - minY = 0 - } else { - minY = elo.Y - } - if els.Height <= vws.Height+elo.Y { - maxY = els.Height - } else { - maxY = vws.Height + elo.Y - } - return -} - -// ---------------------------------------- -// Misc simple types - -type Padding struct { - Left int - Top int - Right int - Bottom int -} - -func (pd Padding) GetPadding() Padding { - return pd -} - -// A border can only have width 0 or 1, and is part of the padding. -// Each string should represent a character of width 1. -type Border struct { - Corners [4]string // starts upper-left and clockwise, "" draws no corner. - TopLine []string // nil if no top border. - BotLine []string // nil if no bottom border. - LeftLine []string // nil if no left border. - RightLine []string // nil if no right border. -} - -func DefaultBorder() Border { - return Border{ - Corners: [4]string{ - string(tcell.RuneULCorner), - string(tcell.RuneURCorner), - string(tcell.RuneLRCorner), - string(tcell.RuneLLCorner), - }, - TopLine: []string{string(tcell.RuneHLine)}, - BotLine: []string{string(tcell.RuneHLine)}, - LeftLine: []string{string(tcell.RuneVLine)}, - RightLine: []string{string(tcell.RuneVLine)}, - } -} - -func LeftBorder() Border { - return Border{ - Corners: [4]string{ - string("\u2553"), - "", - "", - string("\u2559"), - }, - LeftLine: []string{ - string("\u2551"), - }, - } -} - -func orSpace(chr string) string { - if chr == "" { - return " " - } else { - return chr - } -} - -func (br *Border) GetCorner(i int) string { - if br == nil { - return " " - } else { - return orSpace(br.Corners[i]) - } -} - -func (br *Border) TLCorner() string { - return br.GetCorner(0) -} - -func (br *Border) TRCorner() string { - return br.GetCorner(1) -} - -func (br *Border) BRCorner() string { - return br.GetCorner(2) -} - -func (br *Border) BLCorner() string { - return br.GetCorner(3) -} - -func (br *Border) TopBorder(x int) string { - if br == nil || br.TopLine == nil { - return " " - } else { - return br.TopLine[x%len(br.TopLine)] - } -} - -func (br *Border) BottomBorder(x int) string { - if br == nil || br.BotLine == nil { - return " " - } else { - return br.BotLine[x%len(br.BotLine)] - } -} - -func (br *Border) LeftBorder(y int) string { - if br == nil || br.LeftLine == nil { - return " " - } else { - return br.LeftLine[y%len(br.LeftLine)] - } -} - -func (br *Border) RightBorder(y int) string { - if br == nil || br.RightLine == nil { - return " " - } else { - return br.RightLine[y%len(br.RightLine)] - } -} - -type Size struct { - Width int - Height int // -1 if not set. -} - -func (sz Size) String() string { - return fmt.Sprintf("{%d,%d}", sz.Width, sz.Height) -} - -func (sz Size) IsZero() bool { - return sz.Width == 0 && sz.Height == 0 -} - -func (sz Size) GetSize() Size { - return sz -} - -// zero widths or heights are valid. -func (sz Size) IsValid() bool { - return 0 <= sz.Width && 0 <= sz.Height -} - -func (sz Size) IsPositive() bool { - return 0 < sz.Width && 0 < sz.Height -} - -func (sz Size) SubCoord(crd Coord) Size { - if !crd.IsNonNegative() { - panic("should not happen") - } - sz2 := Size{ - Width: sz.Width - crd.X, - Height: sz.Height - crd.Y, - } - if !sz2.IsValid() { - panic("should not happen") - } - return sz2 -} - -type Coord struct { - X int - Y int -} - -func (crd Coord) GetCoord() Coord { - return crd -} - -func (crd *Coord) SetCoord(nc Coord) { - *crd = nc -} - -func (crd Coord) IsNonNegative() bool { - return 0 <= crd.X && 0 <= crd.Y -} - -func (crd Coord) Neg() Coord { - return Coord{ - X: -crd.X, - Y: -crd.Y, - } -} - -func (crd Coord) Add(crd2 Coord) Coord { - return Coord{ - X: crd.X + crd2.X, - Y: crd.Y + crd2.Y, - } -} - -func (crd Coord) Sub(crd2 Coord) Coord { - return Coord{ - X: crd.X - crd2.X, - Y: crd.Y - crd2.Y, - } -} diff --git a/misc/logos/types_test.go b/misc/logos/types_test.go deleted file mode 100644 index 5960783dc342..000000000000 --- a/misc/logos/types_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package logos - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestNewPage1(t *testing.T) { - page := NewPage("this is a new string", 40, false, nil) - require.NotNil(t, page) - size := page.Size - require.Equal(t, Size{Width: 20, Height: 1}, size) -} - -func TestNewPage2(t *testing.T) { - page := NewPage("this is a new string", 10, false, nil) - require.NotNil(t, page) - size := page.Size - /* - 0123456789 - this is a - new string - */ - require.Equal(t, Size{Width: 10, Height: 2}, size) - require.Equal(t, Coord{0, 0}, page.Elems[0].GetCoord()) - require.Equal(t, Coord{5, 0}, page.Elems[1].GetCoord()) - require.Equal(t, Coord{8, 0}, page.Elems[2].GetCoord()) - require.Equal(t, Coord{0, 1}, page.Elems[3].GetCoord()) - require.Equal(t, Coord{4, 1}, page.Elems[4].GetCoord()) - require.Equal(t, 5, len(page.Elems)) -} - -func TestNewPageSprint(t *testing.T) { - t.Skip("test failing") - page := NewPage("this is a new string", 10, false, nil) - require.NotNil(t, page) - /* - 0123456789 - this is a - new string - */ - bpv := NewBufferedElemView(page, Size{}) - bpv.Render() - out := bpv.Sprint() - require.Equal(t, "this is a \nnew string", out) -} diff --git a/misc/logos/unicode.go b/misc/logos/unicode.go deleted file mode 100644 index 924edecc2c57..000000000000 --- a/misc/logos/unicode.go +++ /dev/null @@ -1,86 +0,0 @@ -package logos - -func isCombining(r rune) bool { - return inTable(r, combining) -} - -// ---------------------------------------- -// from https://github.com/mattn/go-runewidth -// runewidth doesn't expose whether a character is combining or not. -// TODO might as well fork both runewidth and tcell. - -var combining = table{ - {0x0300, 0x036F}, - {0x0483, 0x0489}, - {0x07EB, 0x07F3}, - {0x0C00, 0x0C00}, - {0x0C04, 0x0C04}, - {0x0D00, 0x0D01}, - {0x135D, 0x135F}, - {0x1A7F, 0x1A7F}, - {0x1AB0, 0x1AC0}, - {0x1B6B, 0x1B73}, - {0x1DC0, 0x1DF9}, - {0x1DFB, 0x1DFF}, - {0x20D0, 0x20F0}, - {0x2CEF, 0x2CF1}, - {0x2DE0, 0x2DFF}, - {0x3099, 0x309A}, - {0xA66F, 0xA672}, - {0xA674, 0xA67D}, - {0xA69E, 0xA69F}, - {0xA6F0, 0xA6F1}, - {0xA8E0, 0xA8F1}, - {0xFE20, 0xFE2F}, - {0x101FD, 0x101FD}, - {0x10376, 0x1037A}, - {0x10EAB, 0x10EAC}, - {0x10F46, 0x10F50}, - {0x11300, 0x11301}, - {0x1133B, 0x1133C}, - {0x11366, 0x1136C}, - {0x11370, 0x11374}, - {0x16AF0, 0x16AF4}, - {0x1D165, 0x1D169}, - {0x1D16D, 0x1D172}, - {0x1D17B, 0x1D182}, - {0x1D185, 0x1D18B}, - {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, - {0x1E000, 0x1E006}, - {0x1E008, 0x1E018}, - {0x1E01B, 0x1E021}, - {0x1E023, 0x1E024}, - {0x1E026, 0x1E02A}, - {0x1E8D0, 0x1E8D6}, -} - -type interval struct { - first rune - last rune -} - -type table []interval - -func inTable(r rune, t table) bool { - if r < t[0].first { - return false - } - - bot := 0 - top := len(t) - 1 - for top >= bot { - mid := (bot + top) >> 1 - - switch { - case t[mid].last < r: - bot = mid + 1 - case t[mid].first > r: - top = mid - 1 - default: - return true - } - } - - return false -} From 115417274c4c3dce4a26393755763098e6172a94 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 22:40:37 -0400 Subject: [PATCH 08/31] chore: remove vmkeeper.maxcycles (#2993) Let's remove the `vn.maxCycles` variable from the VM keeper so that it relies solely on the built-in gas system. `maxCycles` remains an option on `gno.Machine` for blockchainless and gasless experiences. --------- Signed-off-by: moul <94029+moul@users.noreply.github.com> Co-authored-by: Morgan Bazalgette --- contribs/gnodev/pkg/dev/node.go | 7 +- gno.land/pkg/gnoland/app.go | 3 +- gno.land/pkg/gnoland/node_inmemory.go | 10 +- .../pkg/gnoland/{vals.go => validators.go} | 0 gno.land/pkg/sdk/vm/common_test.go | 2 +- gno.land/pkg/sdk/vm/keeper.go | 103 ++++++++---------- 6 files changed, 55 insertions(+), 70 deletions(-) rename gno.land/pkg/gnoland/{vals.go => validators.go} (100%) diff --git a/contribs/gnodev/pkg/dev/node.go b/contribs/gnodev/pkg/dev/node.go index c3e70366fb2e..0e1099eef881 100644 --- a/contribs/gnodev/pkg/dev/node.go +++ b/contribs/gnodev/pkg/dev/node.go @@ -565,9 +565,8 @@ func newNodeConfig(tmc *tmcfg.Config, chainid string, appstate gnoland.GnoGenesi } return &gnoland.InMemoryNodeConfig{ - PrivValidator: pv, - TMConfig: tmc, - Genesis: genesis, - GenesisMaxVMCycles: 100_000_000, + PrivValidator: pv, + TMConfig: tmc, + Genesis: genesis, } } diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 2380658c6e9e..ca746dbe386b 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -34,7 +34,6 @@ type AppOptions struct { DB dbm.DB // required Logger *slog.Logger // required EventSwitch events.EventSwitch // required - MaxCycles int64 // hard limit for cycles in GnoVM InitChainerConfig // options related to InitChainer } @@ -88,7 +87,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { // Construct keepers. acctKpr := auth.NewAccountKeeper(mainKey, ProtoGnoAccount) bankKpr := bank.NewBankKeeper(acctKpr) - vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, cfg.MaxCycles) + vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr) // Set InitChainer icc := cfg.InitChainerConfig diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go index d168c9556071..f81838e1eb3e 100644 --- a/gno.land/pkg/gnoland/node_inmemory.go +++ b/gno.land/pkg/gnoland/node_inmemory.go @@ -20,11 +20,10 @@ import ( ) type InMemoryNodeConfig struct { - PrivValidator bft.PrivValidator // identity of the validator - Genesis *bft.GenesisDoc - TMConfig *tmcfg.Config - GenesisMaxVMCycles int64 - DB *memdb.MemDB // will be initialized if nil + PrivValidator bft.PrivValidator // identity of the validator + Genesis *bft.GenesisDoc + TMConfig *tmcfg.Config + DB *memdb.MemDB // will be initialized if nil // If StdlibDir not set, then it's filepath.Join(TMConfig.RootDir, "gnovm", "stdlibs") InitChainerConfig @@ -106,7 +105,6 @@ func NewInMemoryNode(logger *slog.Logger, cfg *InMemoryNodeConfig) (*node.Node, // Initialize the application with the provided options gnoApp, err := NewAppWithOptions(&AppOptions{ Logger: logger, - MaxCycles: cfg.GenesisMaxVMCycles, DB: cfg.DB, EventSwitch: evsw, InitChainerConfig: cfg.InitChainerConfig, diff --git a/gno.land/pkg/gnoland/vals.go b/gno.land/pkg/gnoland/validators.go similarity index 100% rename from gno.land/pkg/gnoland/vals.go rename to gno.land/pkg/gnoland/validators.go diff --git a/gno.land/pkg/sdk/vm/common_test.go b/gno.land/pkg/sdk/vm/common_test.go index 43a8fe1fbece..66975fba923a 100644 --- a/gno.land/pkg/sdk/vm/common_test.go +++ b/gno.land/pkg/sdk/vm/common_test.go @@ -47,7 +47,7 @@ func _setupTestEnv(cacheStdlibs bool) testEnv { ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNoopLogger()) acck := authm.NewAccountKeeper(iavlCapKey, std.ProtoBaseAccount) bank := bankm.NewBankKeeper(acck) - vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, 100_000_000) + vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank) mcw := ms.MultiCacheWrap() vmk.Initialize(log.NewNoopLogger(), mcw) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 365473b3e7a5..f069cce37230 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -62,8 +62,6 @@ type VMKeeper struct { // cached, the DeliverTx persistent state. gnoStore gno.Store - - maxCycles int64 // max allowed cylces on VM executions } // NewVMKeeper returns a new VMKeeper. @@ -72,15 +70,13 @@ func NewVMKeeper( iavlKey store.StoreKey, acck auth.AccountKeeper, bank bank.BankKeeper, - maxCycles int64, ) *VMKeeper { // TODO: create an Options struct to avoid too many constructor parameters vmk := &VMKeeper{ - baseKey: baseKey, - iavlKey: iavlKey, - acck: acck, - bank: bank, - maxCycles: maxCycles, + baseKey: baseKey, + iavlKey: iavlKey, + acck: acck, + bank: bank, } return vmk } @@ -267,13 +263,12 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: store, - Context: msgCtx, - Alloc: store.GetAllocator(), - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: store, + Context: msgCtx, + Alloc: store.GetAllocator(), + GasMeter: ctx.GasMeter(), }) defer m.Release() @@ -368,13 +363,12 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // Parse and run the files, construct *PV. m2 := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) defer m2.Release() defer func() { @@ -469,13 +463,12 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { // Construct machine and evaluate. m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: gnostore.GetAllocator(), - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: gnostore.GetAllocator(), + GasMeter: ctx.GasMeter(), }) defer m.Release() m.SetActivePackage(mpv) @@ -569,13 +562,12 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { buf := new(bytes.Buffer) m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: buf, - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: buf, + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) // XXX MsgRun does not have pkgPath. How do we find it on chain? defer m.Release() @@ -596,13 +588,12 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { m2 := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: buf, - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: buf, + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) defer m2.Release() m2.SetActivePackage(pv) @@ -728,13 +719,12 @@ func (vm *VMKeeper) QueryEval(ctx sdk.Context, pkgPath string, expr string) (res } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: alloc, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: alloc, + GasMeter: ctx.GasMeter(), }) defer m.Release() defer func() { @@ -795,13 +785,12 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: alloc, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: alloc, + GasMeter: ctx.GasMeter(), }) defer m.Release() defer func() { From 47fb38907369e4bc23535d71cda58d78f27bb575 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:09:54 +0200 Subject: [PATCH 09/31] chore(deps): bump the actions group across 1 directory with 2 updates (#2995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the actions group with 2 updates in the / directory: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) and [anchore/sbom-action](https://github.com/anchore/sbom-action). Updates `sigstore/cosign-installer` from 3.6.0 to 3.7.0

Release notes

Sourced from sigstore/cosign-installer's releases.

v3.7.0

What's Changed

Full Changelog: https://github.com/sigstore/cosign-installer/compare/v3.6.0...v3.7.0

Commits

Updates `anchore/sbom-action` from 0.17.2 to 0.17.5
Release notes

Sourced from anchore/sbom-action's releases.

v0.17.5

Changes in v0.17.5

v0.17.4

Changes in v0.17.4

v0.17.3

Changes in v0.17.3

Commits
  • 1ca97d9 chore(deps): update Syft to v1.14.2 (#503)
  • 8d0a650 chore(deps): update Syft to v1.14.1 (#502)
  • f5e124a chore(deps): bump peter-evans/create-pull-request from 6.1.0 to 7.0.5 (#493)
  • eff08d0 chore: configure changelog-ignore label (#499)
  • 18f9bde chore: remove snapshot tests; fix deprecation errors for outdated packages (#...
  • 2e87236 add release docs (#500)
  • 4a914bc chore(deps): bump actions/checkout from 4.2.0 to 4.2.1 (#497)
  • 8cb9966 chore(deps): update Syft to v1.14.0 (#498)
  • beb779b Update README to include bit about permissions near the top (#496)
  • 87b3137 chore(deps): update Syft to v1.13.0 (#488)
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] --- .github/workflows/nightlies.yml | 4 +-- .github/workflows/releaser-master.yml | 4 +-- .github/workflows/releaser.yml | 4 +-- go.mod | 5 ---- go.sum | 40 --------------------------- 5 files changed, 6 insertions(+), 51 deletions(-) diff --git a/.github/workflows/nightlies.yml b/.github/workflows/nightlies.yml index e8f3fe4ca5c9..99f9a406ed1f 100644 --- a/.github/workflows/nightlies.yml +++ b/.github/workflows/nightlies.yml @@ -23,8 +23,8 @@ jobs: go-version: "1.22.x" cache: true - - uses: sigstore/cosign-installer@v3.6.0 - - uses: anchore/sbom-action/download-syft@v0.17.2 + - uses: sigstore/cosign-installer@v3.7.0 + - uses: anchore/sbom-action/download-syft@v0.17.5 - uses: docker/login-action@v3 with: diff --git a/.github/workflows/releaser-master.yml b/.github/workflows/releaser-master.yml index 7eda05365325..59dc2ec87051 100644 --- a/.github/workflows/releaser-master.yml +++ b/.github/workflows/releaser-master.yml @@ -24,8 +24,8 @@ jobs: go-version: "1.22.x" cache: true - - uses: sigstore/cosign-installer@v3.6.0 - - uses: anchore/sbom-action/download-syft@v0.17.2 + - uses: sigstore/cosign-installer@v3.7.0 + - uses: anchore/sbom-action/download-syft@v0.17.5 - uses: docker/login-action@v3 with: diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index 5433582cace5..4fb3c279b1f2 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -23,8 +23,8 @@ jobs: go-version: "1.22.x" cache: true - - uses: sigstore/cosign-installer@v3.6.0 - - uses: anchore/sbom-action/download-syft@v0.17.2 + - uses: sigstore/cosign-installer@v3.7.0 + - uses: anchore/sbom-action/download-syft@v0.17.5 - uses: docker/login-action@v3 with: diff --git a/go.mod b/go.mod index d890ab020a49..33f3a0f52125 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/fortytw2/leaktest v1.3.0 - github.com/gdamore/tcell/v2 v2.7.4 github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 github.com/golang/protobuf v1.5.4 github.com/google/gofuzz v1.2.0 @@ -21,7 +20,6 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/gotuna/gotuna v0.6.0 github.com/libp2p/go-buffer-pool v0.1.0 - github.com/mattn/go-runewidth v0.0.16 github.com/pelletier/go-toml v1.9.5 github.com/peterbourgon/ff/v3 v3.4.0 github.com/pmezard/go-difflib v1.0.0 @@ -53,7 +51,6 @@ require ( require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/gdamore/encoding v1.0.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -61,10 +58,8 @@ require ( github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/nxadm/tail v1.4.11 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.4.3 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect diff --git a/go.sum b/go.sum index 9495dd5b4510..55b5681e559e 100644 --- a/go.sum +++ b/go.sum @@ -51,10 +51,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= -github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -110,11 +106,6 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= @@ -136,9 +127,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= -github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= @@ -156,7 +144,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= @@ -190,30 +177,20 @@ go.uber.org/zap/exp v0.2.0/go.mod h1:t0gqAIdh1MfKv9EwN/dLwfZnJxe9ITAZN78HEWPFWDQ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -225,36 +202,19 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 4b6871295b25924e32475bf2b8f90d11377bdd6a Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Tue, 22 Oct 2024 13:55:52 +0200 Subject: [PATCH 10/31] fix(crypto/keys): in dbKeybase.writeInfo, if replacing a name entry, remove the lookup by the old address (#2685) This PR fixes the bug demonstrated in https://github.com/gnolang/gno/pull/2684 : * In `dbKeybase.writeInfo`, add an `error` return and propagate this to all callers (`writeLocalKey`, etc.) . We need `writeInfo` to do some database integrity checks, so it needs to be able to return an error. * Update `dbKeybase.writeInfo` as suggested in [#2684](https://github.com/gnolang/gno/pull/2684) . If an existing name entry is being replaced with new `Info`, then remove the "lookup by address" entry for the existing address. * In `TestKeyManagement`, add a test similar to [#2684](https://github.com/gnolang/gno/pull/2684) , except that after using `CreateAccount` with the same name, expect `GetByAddress` to fail for the obsolete address and its (non-existing) public key. (This test passes.)
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests
Signed-off-by: Jeff Thompson --- tm2/pkg/crypto/keys/keybase.go | 58 +++++++++++++++++++---------- tm2/pkg/crypto/keys/keybase_test.go | 13 +++++++ 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/tm2/pkg/crypto/keys/keybase.go b/tm2/pkg/crypto/keys/keybase.go index c28fd1ef952a..ea3d0546fa0c 100644 --- a/tm2/pkg/crypto/keys/keybase.go +++ b/tm2/pkg/crypto/keys/keybase.go @@ -115,33 +115,32 @@ func (kb dbKeybase) CreateLedger(name string, algo SigningAlgo, hrp string, acco pub := priv.PubKey() // Note: Once Cosmos App v1.3.1 is compulsory, it could be possible to check that pubkey and addr match - return kb.writeLedgerKey(name, pub, *hdPath), nil + return kb.writeLedgerKey(name, pub, *hdPath) } // CreateOffline creates a new reference to an offline keypair. It returns the // created key info. func (kb dbKeybase) CreateOffline(name string, pub crypto.PubKey) (Info, error) { - return kb.writeOfflineKey(name, pub), nil + return kb.writeOfflineKey(name, pub) } // CreateMulti creates a new reference to a multisig (offline) keypair. It // returns the created key info. func (kb dbKeybase) CreateMulti(name string, pub crypto.PubKey) (Info, error) { - return kb.writeMultisigKey(name, pub), nil + return kb.writeMultisigKey(name, pub) } -func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info Info, err error) { +func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (Info, error) { // create master key and derive first key: masterPriv, ch := hd.ComputeMastersFromSeed(seed) derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, fullHdPath) if err != nil { - return + return nil, err } // use possibly blank password to encrypt the private // key and store it. User must enforce good passwords. - info = kb.writeLocalKey(name, secp256k1.PrivKeySecp256k1(derivedPriv), passwd) - return + return kb.writeLocalKey(name, secp256k1.PrivKeySecp256k1(derivedPriv), passwd) } // List returns the keys from storage in alphabetical order. @@ -475,41 +474,60 @@ func (kb dbKeybase) CloseDB() { kb.db.Close() } -func (kb dbKeybase) writeLocalKey(name string, priv crypto.PrivKey, passphrase string) Info { +func (kb dbKeybase) writeLocalKey(name string, priv crypto.PrivKey, passphrase string) (Info, error) { // encrypt private key using passphrase privArmor := armor.EncryptArmorPrivKey(priv, passphrase) // make Info pub := priv.PubKey() info := newLocalInfo(name, pub, privArmor) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeLedgerKey(name string, pub crypto.PubKey, path hd.BIP44Params) Info { +func (kb dbKeybase) writeLedgerKey(name string, pub crypto.PubKey, path hd.BIP44Params) (Info, error) { info := newLedgerInfo(name, pub, path) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeOfflineKey(name string, pub crypto.PubKey) Info { +func (kb dbKeybase) writeOfflineKey(name string, pub crypto.PubKey) (Info, error) { info := newOfflineInfo(name, pub) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeMultisigKey(name string, pub crypto.PubKey) Info { +func (kb dbKeybase) writeMultisigKey(name string, pub crypto.PubKey) (Info, error) { info := NewMultiInfo(name, pub) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeInfo(name string, info Info) { +func (kb dbKeybase) writeInfo(name string, info Info) error { // write the info by key key := infoKey(name) + oldInfob := kb.db.Get(key) + if len(oldInfob) > 0 { + // Enforce 1-to-1 name to address. Remove the lookup by the old address + oldInfo, err := readInfo(oldInfob) + if err != nil { + return err + } + kb.db.DeleteSync(addrKey(oldInfo.GetAddress())) + } + serializedInfo := writeInfo(info) kb.db.SetSync(key, serializedInfo) // store a pointer to the infokey by address for fast lookup kb.db.SetSync(addrKey(info.GetAddress()), key) + return nil } func addrKey(address crypto.Address) []byte { diff --git a/tm2/pkg/crypto/keys/keybase_test.go b/tm2/pkg/crypto/keys/keybase_test.go index afcc1c561977..bfb21b46fad6 100644 --- a/tm2/pkg/crypto/keys/keybase_test.go +++ b/tm2/pkg/crypto/keys/keybase_test.go @@ -111,6 +111,19 @@ func TestKeyManagement(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, len(keyS)) + // Lookup by original i2 address + infoByAddress, err := cstore.GetByAddress(i2.GetAddress()) + require.NoError(t, err) + // GetByAddress should return Info with the corresponding public key + require.Equal(t, infoByAddress.GetPubKey(), i2.GetPubKey()) + // Replace n2 with a new address + mn2New := `fancy assault crane note start invite ladder ordinary gold amateur check cousin text mercy speak chuckle wine raw chief isolate swallow cushion wrist piece` + _, err = cstore.CreateAccount(n2, mn2New, bip39Passphrase, p2, 0, 0) + require.NoError(t, err) + // Check that CreateAccount removes the entry for the original address (public key) + _, err = cstore.GetByAddress(i2.GetAddress()) + require.NotNil(t, err) + // addr cache gets nuked - and test skip flag err = cstore.Delete(n2, "", true) require.NoError(t, err) From ec222ec8086bc07139bbdf9ef9e9448eaded5f52 Mon Sep 17 00:00:00 2001 From: Stefan Nikolic Date: Tue, 22 Oct 2024 15:35:43 +0200 Subject: [PATCH 11/31] feat(examples): add interactive realm `r/stefann/home` (#2918) # Description: This PR finalizes the core functionality of my home realm project, focusing on a dynamic and interactive home realm experience, driven by GNOT donations. The following key features and enhancements are introduced in this PR: ## Key Features: - **Dynamic Background Change:** - Implemented sequential background changes triggered by GNOT donations. Each donation updates the city background in a fixed order, cycling through a predefined set of cities. The background change is seamless, offering a "traveling" experience for donors. - **Sponsor Leaderboard:** - Added a sponsor leaderboard to showcase the top contributors based on their GNOT donations. The list displays the addresses of the top sponsors, formatted for readability (first and last characters with ellipses), and limits the displayed sponsors to the configurable `maxSponsors` setting. - **Donation Validation:** - Introduced a strict GNOT validation check. The system now rejects any donation attempts that don't include GNOT, ensuring only valid contributions update the state of the realm. - **Owner Withdrawal of Donations:** - Implemented a feature that allows the realm owner to withdraw accumulated GNOT donations, providing control over the funds contributed by supporters. - **Home Realm Configurations:** - **Cities:** Cities can be dynamically updated to refresh the possible backgrounds. - **Maximum Sponsors:** Admins can configure the number of sponsors shown on the leaderboard with the `maxSponsors` setting. - **Jar Link:** Admins can update the link to the donation jar. --- examples/gno.land/r/stefann/home/gno.mod | 9 + examples/gno.land/r/stefann/home/home.gno | 303 ++++++++++++++++++ .../gno.land/r/stefann/home/home_test.gno | 291 +++++++++++++++++ examples/gno.land/r/stefann/registry/gno.mod | 3 + .../gno.land/r/stefann/registry/registry.gno | 51 +++ 5 files changed, 657 insertions(+) create mode 100644 examples/gno.land/r/stefann/home/gno.mod create mode 100644 examples/gno.land/r/stefann/home/home.gno create mode 100644 examples/gno.land/r/stefann/home/home_test.gno create mode 100644 examples/gno.land/r/stefann/registry/gno.mod create mode 100644 examples/gno.land/r/stefann/registry/registry.gno diff --git a/examples/gno.land/r/stefann/home/gno.mod b/examples/gno.land/r/stefann/home/gno.mod new file mode 100644 index 000000000000..dd556e7f817b --- /dev/null +++ b/examples/gno.land/r/stefann/home/gno.mod @@ -0,0 +1,9 @@ +module gno.land/r/stefann/home + +require ( + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/ownable v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/stefann/registry v0.0.0-latest +) diff --git a/examples/gno.land/r/stefann/home/home.gno b/examples/gno.land/r/stefann/home/home.gno new file mode 100644 index 000000000000..f40329ebf7e2 --- /dev/null +++ b/examples/gno.land/r/stefann/home/home.gno @@ -0,0 +1,303 @@ +package home + +import ( + "sort" + "std" + "strings" + + "gno.land/p/demo/avl" + "gno.land/p/demo/ownable" + "gno.land/p/demo/ufmt" + + "gno.land/r/stefann/registry" +) + +type City struct { + Name string + URL string +} + +type Sponsor struct { + Address std.Address + Amount std.Coins +} + +type Profile struct { + pfp string + aboutMe []string +} + +type Travel struct { + cities []City + currentCityIndex int + jarLink string +} + +type Sponsorship struct { + maxSponsors int + sponsors *avl.Tree + DonationsCount int + sponsorsCount int +} + +var ( + profile Profile + travel Travel + sponsorship Sponsorship + owner *ownable.Ownable +) + +func init() { + owner = ownable.NewWithAddress(registry.MainAddr()) + + profile = Profile{ + pfp: "https://i.ibb.co/Bc5YNCx/DSC-0095a.jpg", + aboutMe: []string{ + `### About Me`, + `Hey there! I’m Stefan, a student of Computer Science. I’m all about exploring and adventure — whether it’s diving into the latest tech or discovering a new city, I’m always up for the challenge!`, + + `### Contributions`, + `I'm just getting started, but you can follow my journey through Gno.land right [here](https://github.com/gnolang/hackerspace/issues/94) 🔗`, + }, + } + + travel = Travel{ + cities: []City{ + {Name: "Venice", URL: "https://i.ibb.co/1mcZ7b1/venice.jpg"}, + {Name: "Tokyo", URL: "https://i.ibb.co/wNDJv3H/tokyo.jpg"}, + {Name: "São Paulo", URL: "https://i.ibb.co/yWMq2Sn/sao-paulo.jpg"}, + {Name: "Toronto", URL: "https://i.ibb.co/pb95HJB/toronto.jpg"}, + {Name: "Bangkok", URL: "https://i.ibb.co/pQy3w2g/bangkok.jpg"}, + {Name: "New York", URL: "https://i.ibb.co/6JWLm0h/new-york.jpg"}, + {Name: "Paris", URL: "https://i.ibb.co/q9vf6Hs/paris.jpg"}, + {Name: "Kandersteg", URL: "https://i.ibb.co/60DzywD/kandersteg.jpg"}, + {Name: "Rothenburg", URL: "https://i.ibb.co/cr8d2rQ/rothenburg.jpg"}, + {Name: "Capetown", URL: "https://i.ibb.co/bPGn0v3/capetown.jpg"}, + {Name: "Sydney", URL: "https://i.ibb.co/TBNzqfy/sydney.jpg"}, + {Name: "Oeschinen Lake", URL: "https://i.ibb.co/QJQwp2y/oeschinen-lake.jpg"}, + {Name: "Barra Grande", URL: "https://i.ibb.co/z4RXKc1/barra-grande.jpg"}, + {Name: "London", URL: "https://i.ibb.co/CPGtvgr/london.jpg"}, + }, + currentCityIndex: 0, + jarLink: "https://TODO", // This value should be injected through UpdateJarLink after deployment. + } + + sponsorship = Sponsorship{ + maxSponsors: 5, + sponsors: avl.NewTree(), + DonationsCount: 0, + sponsorsCount: 0, + } +} + +func UpdateCities(newCities []City) { + owner.AssertCallerIsOwner() + travel.cities = newCities +} + +func AddCities(newCities ...City) { + owner.AssertCallerIsOwner() + + travel.cities = append(travel.cities, newCities...) +} + +func UpdateJarLink(newLink string) { + owner.AssertCallerIsOwner() + travel.jarLink = newLink +} + +func UpdatePFP(url string) { + owner.AssertCallerIsOwner() + profile.pfp = url +} + +func UpdateAboutMe(aboutMeStr string) { + owner.AssertCallerIsOwner() + profile.aboutMe = strings.Split(aboutMeStr, "|") +} + +func AddAboutMeRows(newRows ...string) { + owner.AssertCallerIsOwner() + + profile.aboutMe = append(profile.aboutMe, newRows...) +} + +func UpdateMaxSponsors(newMax int) { + owner.AssertCallerIsOwner() + if newMax <= 0 { + panic("maxSponsors must be greater than zero") + } + sponsorship.maxSponsors = newMax +} + +func Donate() { + address := std.GetOrigCaller() + amount := std.GetOrigSend() + + if amount.AmountOf("ugnot") == 0 { + panic("Donation must include GNOT") + } + + existingAmount, exists := sponsorship.sponsors.Get(address.String()) + if exists { + updatedAmount := existingAmount.(std.Coins).Add(amount) + sponsorship.sponsors.Set(address.String(), updatedAmount) + } else { + sponsorship.sponsors.Set(address.String(), amount) + sponsorship.sponsorsCount++ + } + + travel.currentCityIndex++ + sponsorship.DonationsCount++ + + banker := std.GetBanker(std.BankerTypeRealmSend) + ownerAddr := registry.MainAddr() + banker.SendCoins(std.CurrentRealm().Addr(), ownerAddr, banker.GetCoins(std.CurrentRealm().Addr())) +} + +type SponsorSlice []Sponsor + +func (s SponsorSlice) Len() int { + return len(s) +} + +func (s SponsorSlice) Less(i, j int) bool { + return s[i].Amount.AmountOf("ugnot") > s[j].Amount.AmountOf("ugnot") +} + +func (s SponsorSlice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func GetTopSponsors() []Sponsor { + var sponsorSlice SponsorSlice + + sponsorship.sponsors.Iterate("", "", func(key string, value interface{}) bool { + addr := std.Address(key) + amount := value.(std.Coins) + sponsorSlice = append(sponsorSlice, Sponsor{Address: addr, Amount: amount}) + return false + }) + + sort.Sort(sponsorSlice) + return sponsorSlice +} + +func GetTotalDonations() int { + total := 0 + sponsorship.sponsors.Iterate("", "", func(key string, value interface{}) bool { + total += int(value.(std.Coins).AmountOf("ugnot")) + return false + }) + return total +} + +func Render(path string) string { + out := ufmt.Sprintf("# Exploring %s!\n\n", travel.cities[travel.currentCityIndex].Name) + + out += renderAboutMe() + out += "\n\n" + out += renderTips() + + return out +} + +func renderAboutMe() string { + out := "
" + + out += "
\n\n" + + out += ufmt.Sprintf("
\n\n", travel.cities[travel.currentCityIndex%len(travel.cities)].URL) + + out += ufmt.Sprintf("my profile pic\n\n", profile.pfp) + + out += "
\n\n" + + for _, rows := range profile.aboutMe { + out += "
\n\n" + out += rows + "\n\n" + out += "
\n\n" + } + + out += "
\n\n" + + return out +} + +func renderTips() string { + out := `
` + "\n\n" + + out += `
` + "\n" + + out += `

Help Me Travel The World

` + "\n\n" + + out += renderTipsJar() + "\n" + + out += ufmt.Sprintf(`I am currently in %s,
tip the jar to send me somewhere else!
`, travel.cities[travel.currentCityIndex].Name) + + out += `
Click the jar, tip in GNOT coins, and watch my background change as I head to a new adventure!

` + "\n\n" + + out += renderSponsors() + + out += `
` + "\n\n" + + out += `
` + "\n" + + return out +} + +func formatAddress(address string) string { + if len(address) <= 8 { + return address + } + return address[:4] + "..." + address[len(address)-4:] +} + +func renderSponsors() string { + out := `

Sponsor Leaderboard

` + "\n" + + if sponsorship.sponsorsCount == 0 { + return out + `

No sponsors yet. Be the first to tip the jar!

` + "\n" + } + + topSponsors := GetTopSponsors() + numSponsors := len(topSponsors) + if numSponsors > sponsorship.maxSponsors { + numSponsors = sponsorship.maxSponsors + } + + out += `
    ` + "\n" + + for i := 0; i < numSponsors; i++ { + sponsor := topSponsors[i] + isLastItem := (i == numSponsors-1) + + padding := "10px 5px" + border := "border-bottom: 1px solid #ddd;" + + if isLastItem { + padding = "8px 5px" + border = "" + } + + out += ufmt.Sprintf( + `
  • + %d. %s + %s +
  • `, + padding, border, i+1, formatAddress(sponsor.Address.String()), sponsor.Amount.String(), + ) + } + + return out +} + +func renderTipsJar() string { + out := ufmt.Sprintf(``, travel.jarLink) + "\n" + + out += `Tips Jar` + "\n" + + out += `` + "\n" + + return out +} diff --git a/examples/gno.land/r/stefann/home/home_test.gno b/examples/gno.land/r/stefann/home/home_test.gno new file mode 100644 index 000000000000..ca146b9eb130 --- /dev/null +++ b/examples/gno.land/r/stefann/home/home_test.gno @@ -0,0 +1,291 @@ +package home + +import ( + "std" + "strings" + "testing" + + "gno.land/p/demo/avl" + "gno.land/p/demo/testutils" +) + +func TestUpdatePFP(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + profile.pfp = "" + + UpdatePFP("https://example.com/pic.png") + + if profile.pfp != "https://example.com/pic.png" { + t.Fatalf("expected pfp to be https://example.com/pic.png, got %s", profile.pfp) + } +} + +func TestUpdateAboutMe(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + profile.aboutMe = []string{} + + UpdateAboutMe("This is my new bio.|I love coding!") + + expected := []string{"This is my new bio.", "I love coding!"} + + if len(profile.aboutMe) != len(expected) { + t.Fatalf("expected aboutMe to have length %d, got %d", len(expected), len(profile.aboutMe)) + } + + for i := range profile.aboutMe { + if profile.aboutMe[i] != expected[i] { + t.Fatalf("expected aboutMe[%d] to be %s, got %s", i, expected[i], profile.aboutMe[i]) + } + } +} + +func TestUpdateCities(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + travel.cities = []City{} + + newCities := []City{ + {Name: "Berlin", URL: "https://example.com/berlin.jpg"}, + {Name: "Vienna", URL: "https://example.com/vienna.jpg"}, + } + + UpdateCities(newCities) + + if len(travel.cities) != 2 { + t.Fatalf("expected 2 cities, got %d", len(travel.cities)) + } + + if travel.cities[0].Name != "Berlin" || travel.cities[1].Name != "Vienna" { + t.Fatalf("expected cities to be updated to Berlin and Vienna, got %+v", travel.cities) + } +} + +func TestUpdateJarLink(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + travel.jarLink = "" + + UpdateJarLink("https://example.com/jar") + + if travel.jarLink != "https://example.com/jar" { + t.Fatalf("expected jarLink to be https://example.com/jar, got %s", travel.jarLink) + } +} + +func TestUpdateMaxSponsors(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + sponsorship.maxSponsors = 0 + + UpdateMaxSponsors(10) + + if sponsorship.maxSponsors != 10 { + t.Fatalf("expected maxSponsors to be 10, got %d", sponsorship.maxSponsors) + } + + defer func() { + if r := recover(); r == nil { + t.Fatalf("expected panic for setting maxSponsors to 0") + } + }() + UpdateMaxSponsors(0) +} + +func TestAddCities(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + travel.cities = []City{} + + AddCities(City{Name: "Berlin", URL: "https://example.com/berlin.jpg"}) + + if len(travel.cities) != 1 { + t.Fatalf("expected 1 city, got %d", len(travel.cities)) + } + if travel.cities[0].Name != "Berlin" || travel.cities[0].URL != "https://example.com/berlin.jpg" { + t.Fatalf("expected city to be Berlin, got %+v", travel.cities[0]) + } + + AddCities( + City{Name: "Paris", URL: "https://example.com/paris.jpg"}, + City{Name: "Tokyo", URL: "https://example.com/tokyo.jpg"}, + ) + + if len(travel.cities) != 3 { + t.Fatalf("expected 3 cities, got %d", len(travel.cities)) + } + if travel.cities[1].Name != "Paris" || travel.cities[2].Name != "Tokyo" { + t.Fatalf("expected cities to be Paris and Tokyo, got %+v", travel.cities[1:]) + } +} + +func TestAddAboutMeRows(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + profile.aboutMe = []string{} + + AddAboutMeRows("I love exploring new technologies!") + + if len(profile.aboutMe) != 1 { + t.Fatalf("expected 1 aboutMe row, got %d", len(profile.aboutMe)) + } + if profile.aboutMe[0] != "I love exploring new technologies!" { + t.Fatalf("expected first aboutMe row to be 'I love exploring new technologies!', got %s", profile.aboutMe[0]) + } + + AddAboutMeRows("Travel is my passion!", "Always learning.") + + if len(profile.aboutMe) != 3 { + t.Fatalf("expected 3 aboutMe rows, got %d", len(profile.aboutMe)) + } + if profile.aboutMe[1] != "Travel is my passion!" || profile.aboutMe[2] != "Always learning." { + t.Fatalf("expected aboutMe rows to be 'Travel is my passion!' and 'Always learning.', got %+v", profile.aboutMe[1:]) + } +} + +func TestDonate(t *testing.T) { + var user = testutils.TestAddress("user") + std.TestSetOrigCaller(user) + + sponsorship.sponsors = avl.NewTree() + sponsorship.DonationsCount = 0 + sponsorship.sponsorsCount = 0 + travel.currentCityIndex = 0 + + coinsSent := std.NewCoins(std.NewCoin("ugnot", 500)) + std.TestSetOrigSend(coinsSent, std.NewCoins()) + Donate() + + existingAmount, exists := sponsorship.sponsors.Get(string(user)) + if !exists { + t.Fatalf("expected sponsor to be added, but it was not found") + } + + if existingAmount.(std.Coins).AmountOf("ugnot") != 500 { + t.Fatalf("expected donation amount to be 500ugnot, got %d", existingAmount.(std.Coins).AmountOf("ugnot")) + } + + if sponsorship.DonationsCount != 1 { + t.Fatalf("expected DonationsCount to be 1, got %d", sponsorship.DonationsCount) + } + + if sponsorship.sponsorsCount != 1 { + t.Fatalf("expected sponsorsCount to be 1, got %d", sponsorship.sponsorsCount) + } + + if travel.currentCityIndex != 1 { + t.Fatalf("expected currentCityIndex to be 1, got %d", travel.currentCityIndex) + } + + coinsSent = std.NewCoins(std.NewCoin("ugnot", 300)) + std.TestSetOrigSend(coinsSent, std.NewCoins()) + Donate() + + existingAmount, exists = sponsorship.sponsors.Get(string(user)) + if !exists { + t.Fatalf("expected sponsor to exist after second donation, but it was not found") + } + + if existingAmount.(std.Coins).AmountOf("ugnot") != 800 { + t.Fatalf("expected total donation amount to be 800ugnot, got %d", existingAmount.(std.Coins).AmountOf("ugnot")) + } + + if sponsorship.DonationsCount != 2 { + t.Fatalf("expected DonationsCount to be 2 after second donation, got %d", sponsorship.DonationsCount) + } + + if travel.currentCityIndex != 2 { + t.Fatalf("expected currentCityIndex to be 2 after second donation, got %d", travel.currentCityIndex) + } +} + +func TestGetTopSponsors(t *testing.T) { + var user = testutils.TestAddress("user") + std.TestSetOrigCaller(user) + + sponsorship.sponsors = avl.NewTree() + sponsorship.sponsorsCount = 0 + + sponsorship.sponsors.Set("g1address1", std.NewCoins(std.NewCoin("ugnot", 300))) + sponsorship.sponsors.Set("g1address2", std.NewCoins(std.NewCoin("ugnot", 500))) + sponsorship.sponsors.Set("g1address3", std.NewCoins(std.NewCoin("ugnot", 200))) + sponsorship.sponsorsCount = 3 + + topSponsors := GetTopSponsors() + + if len(topSponsors) != 3 { + t.Fatalf("expected 3 sponsors, got %d", len(topSponsors)) + } + + if topSponsors[0].Address.String() != "g1address2" || topSponsors[0].Amount.AmountOf("ugnot") != 500 { + t.Fatalf("expected top sponsor to be g1address2 with 500ugnot, got %s with %dugnot", topSponsors[0].Address.String(), topSponsors[0].Amount.AmountOf("ugnot")) + } + + if topSponsors[1].Address.String() != "g1address1" || topSponsors[1].Amount.AmountOf("ugnot") != 300 { + t.Fatalf("expected second sponsor to be g1address1 with 300ugnot, got %s with %dugnot", topSponsors[1].Address.String(), topSponsors[1].Amount.AmountOf("ugnot")) + } + + if topSponsors[2].Address.String() != "g1address3" || topSponsors[2].Amount.AmountOf("ugnot") != 200 { + t.Fatalf("expected third sponsor to be g1address3 with 200ugnot, got %s with %dugnot", topSponsors[2].Address.String(), topSponsors[2].Amount.AmountOf("ugnot")) + } +} + +func TestGetTotalDonations(t *testing.T) { + var user = testutils.TestAddress("user") + std.TestSetOrigCaller(user) + + sponsorship.sponsors = avl.NewTree() + sponsorship.sponsorsCount = 0 + + sponsorship.sponsors.Set("g1address1", std.NewCoins(std.NewCoin("ugnot", 300))) + sponsorship.sponsors.Set("g1address2", std.NewCoins(std.NewCoin("ugnot", 500))) + sponsorship.sponsors.Set("g1address3", std.NewCoins(std.NewCoin("ugnot", 200))) + sponsorship.sponsorsCount = 3 + + totalDonations := GetTotalDonations() + + if totalDonations != 1000 { + t.Fatalf("expected total donations to be 1000ugnot, got %dugnot", totalDonations) + } +} + +func TestRender(t *testing.T) { + travel.currentCityIndex = 0 + travel.cities = []City{ + {Name: "Venice", URL: "https://example.com/venice.jpg"}, + {Name: "Paris", URL: "https://example.com/paris.jpg"}, + } + + output := Render("") + + expectedCity := "Venice" + if !strings.Contains(output, expectedCity) { + t.Fatalf("expected output to contain city name '%s', got %s", expectedCity, output) + } + + expectedURL := "https://example.com/venice.jpg" + if !strings.Contains(output, expectedURL) { + t.Fatalf("expected output to contain city URL '%s', got %s", expectedURL, output) + } + + travel.currentCityIndex = 1 + output = Render("") + + expectedCity = "Paris" + if !strings.Contains(output, expectedCity) { + t.Fatalf("expected output to contain city name '%s', got %s", expectedCity, output) + } + + expectedURL = "https://example.com/paris.jpg" + if !strings.Contains(output, expectedURL) { + t.Fatalf("expected output to contain city URL '%s', got %s", expectedURL, output) + } +} diff --git a/examples/gno.land/r/stefann/registry/gno.mod b/examples/gno.land/r/stefann/registry/gno.mod new file mode 100644 index 000000000000..5ed3e4916e26 --- /dev/null +++ b/examples/gno.land/r/stefann/registry/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/stefann/registry + +require gno.land/p/demo/ownable v0.0.0-latest diff --git a/examples/gno.land/r/stefann/registry/registry.gno b/examples/gno.land/r/stefann/registry/registry.gno new file mode 100644 index 000000000000..6f56d105e4b6 --- /dev/null +++ b/examples/gno.land/r/stefann/registry/registry.gno @@ -0,0 +1,51 @@ +package registry + +import ( + "errors" + "std" + + "gno.land/p/demo/ownable" +) + +var ( + mainAddr std.Address + backupAddr std.Address + owner *ownable.Ownable +) + +func init() { + mainAddr = "g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8" + backupAddr = "g13awn2575t8s2vf3svlprc4dg0e9z5wchejdxk8" + + owner = ownable.NewWithAddress(mainAddr) +} + +func MainAddr() std.Address { + return mainAddr +} + +func BackupAddr() std.Address { + return backupAddr +} + +func SetMainAddr(addr std.Address) error { + if !addr.IsValid() { + return errors.New("config: invalid address") + } + + owner.AssertCallerIsOwner() + + mainAddr = addr + return nil +} + +func SetBackupAddr(addr std.Address) error { + if !addr.IsValid() { + return errors.New("config: invalid address") + } + + owner.AssertCallerIsOwner() + + backupAddr = addr + return nil +} From 5c876f3787493158faf38b6cc7d28b2d57e417b1 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:45:11 -0400 Subject: [PATCH 12/31] chore(codecov): ignore generated files (#2998) The change does not appear to be applied to my PR #2920, so I am opening a dedicated PR to make Codecov aware. Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .github/codecov.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/codecov.yml b/.github/codecov.yml index ea1c701d946e..d1ecba7ade36 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -39,3 +39,8 @@ flag_management: - type: patch target: auto # Let's decrease this later. threshold: 10 + +ignore: + - "gnovm/stdlibs/generated.go" + - "gnovm/tests/stdlibs/generated.go" + - "**/*.pb.go" From 1a57e81f5e454304dd0de38657d680edef18100d Mon Sep 17 00:00:00 2001 From: Jae Kwon <53785+jaekwon@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:38:00 -0700 Subject: [PATCH 13/31] feat(gnovm): handle loop variables (#2429) # Problem Definition The problem originates from the issue described in [#1135](https://github.com/gnolang/gno/issues/1135). While the full scope of the issue is broader, it fundamentally relates to the concept of loop variable escapes block where it's defined. e.g. 1: ```go package main import "fmt" var s1 []*int func forLoopRef() { defer func() { for i, e := range s1 { fmt.Printf("s1[%d] is: %d\n", i, *e) } }() for i := 0; i < 3; i++ { z := i + 1 s1 = append(s1, &z) } } func main() { forLoopRef() } ``` e.g. 2: ```go package main type f func() var fs []f func forLoopClosure() { defer func() { for _, f := range fs { f() } }() for i := 0; i < 3; i++ { z := i fs = append(fs, func() { println(z) }) } } func main() { forLoopClosure() } ``` e.g. 3: ```go package main func main() { c := 0 closures := []func(){} loop: i := c closures = append(closures, func() { println(i) }) c += 1 if c < 10 { goto loop } for _, cl := range closures { cl() } } ``` # Solution ideas - **identify escaped vars in preprocess**: Detect situations where a loop variable is defined within a loop block(including `for/range` loops or loops constructed using `goto` statements), and escapes the block where it's defined. - **runtime allocation**: Allocate a new heap item for the loop variable in each iteration to ensure each iteration operates with its unique variable instance. - **NOTE1**: this is consistent with Go's Strategy: "Each iteration has its own separate declared variable (or variables) [Go 1.22]. The variable used by the first iteration is declared by the init statement. The variable used by each subsequent iteration is declared implicitly before executing the post statement and initialized to the value of the previous iteration's variable at that moment." - **NOTE2**: the `loopvar` feature of Go 1.22 is not supported in this version, and will be supported in next version. not supporting capture `i` defined in for/range clause; ```go for i := 0; i < 3; i++ { s1 = append(s1, &i) } ``` # Implementation Details **Preprocess Stage(Multi-Phase Preprocessor)**: - **Phase 1: `initStaticBlocks`**: Establish a cascading scope structure where `predefine` is conducted. In this phase Name expressions are initially marked as `NameExprTypeDefine`, which may later be upgraded to `NameExprTypeHeapDefine` if it is determined that they escape the loop block. This phase also supports other processes as a prerequisite[#2077](https://github.com/gnolang/gno/pull/2077). - **Phase 2: `preprocess1`**: This represents the original preprocessing phase(not going into details). - **Phase 3: `findGotoLoopDefines`**: By traversing the AST, any name expression defined in a loop block (for/range, goto) with the attribute `NameExprTypeDefine` is promoted to `NameExprTypeHeapDefine`. This is used in later phase. - **Phase 4: `findLoopUses1`**: Identify the usage of `NameExprTypeHeapDefine` name expressions. If a name expression is used in a function literal or is referrnced(e.g. &a), and it was previously defined as `NameExprTypeHeapDefine`, the `used` name expression is then given the attribute `NameExprTypeHeapUse`. This step finalizes whether a name expression will be allocated on the heap and used from heap. `Closures` represent a particular scenario in this context. Each closure, defined by a funcLitExpr that captures variables, is associated with a HeapCaptures list. This list consists of NameExprs, which are utilized at runtime to obtain the actual variable values for each iteration. Correspondingly, within the funcLitExpr block, a list of placeholder values are defined. These placeholders are populated during the doOpFuncLit phase and subsequently utilized in the `doOpCall` to ensure that each iteration uses the correct data. - **Phase 5: `findLoopUses2`**: Convert non-loop uses of loop-defined names to `NameExprTypeHeapUse`. Also, demote `NameExprTypeHeapDefine` back to `NameExprTypeDefine` if no actual usage is found. Also , as the last phase, attributes no longer needed will be cleaned up after this phase. **Runtime Stage**: 1. **Variable Allocation**: - Modify the runtime so that encountering a `NameExprTypeHeapDefine` triggers the allocation of a new `heapItemValue` for it, which will be used by any `NameExprTypeHeapUse`. 2. **Function Literal Handling**: - During the execution of `doOpFuncLit`, retrieve the `HeapCapture` values (previously allocated heap item values) and fill in the placeholder values within the `funcLitExpr` block. - When invoking the function (`doOpCall`), the `placeHolder` values(fv.Captures) are used to update the execution context, ensuring accurate and consistent results across iterations. --------- Co-authored-by: ltzMaxwell Co-authored-by: Morgan --- .../gno_test/test_with-native-fallback.txtar | 2 +- .../gno/testdata/gno_test/unknow_lib.txtar | 4 +- gnovm/pkg/gnolang/debugger.go | 14 +- gnovm/pkg/gnolang/debugger_test.go | 2 +- gnovm/pkg/gnolang/go2gno.go | 6 +- gnovm/pkg/gnolang/kind_string.go | 9 +- gnovm/pkg/gnolang/machine.go | 30 +- gnovm/pkg/gnolang/nodes.go | 120 ++- gnovm/pkg/gnolang/nodes_string.go | 21 +- gnovm/pkg/gnolang/op_assign.go | 2 +- gnovm/pkg/gnolang/op_call.go | 22 + gnovm/pkg/gnolang/op_decl.go | 4 +- gnovm/pkg/gnolang/op_eval.go | 2 +- gnovm/pkg/gnolang/op_exec.go | 26 +- gnovm/pkg/gnolang/op_expressions.go | 22 +- gnovm/pkg/gnolang/preprocess.go | 789 ++++++++++++++---- gnovm/pkg/gnolang/realm.go | 4 + gnovm/pkg/gnolang/store.go | 2 +- gnovm/pkg/gnolang/transcribe.go | 15 + gnovm/pkg/gnolang/transfield_string.go | 120 +-- gnovm/pkg/gnolang/type_check.go | 30 +- gnovm/pkg/gnolang/types.go | 39 +- gnovm/pkg/gnolang/values.go | 83 +- gnovm/tests/file.go | 59 +- .../more/realm_compositelit_filetest.gno | 6 +- gnovm/tests/files/heap_alloc_defer.gno | 37 + gnovm/tests/files/heap_alloc_defer2.gno | 28 + gnovm/tests/files/heap_alloc_forloop1.gno | 31 + gnovm/tests/files/heap_alloc_forloop1a.gno | 39 + gnovm/tests/files/heap_alloc_forloop1b.gno | 37 + gnovm/tests/files/heap_alloc_forloop2.gno | 33 + gnovm/tests/files/heap_alloc_forloop2a.gno | 34 + gnovm/tests/files/heap_alloc_forloop3.gno | 33 + gnovm/tests/files/heap_alloc_forloop3a.gno | 38 + gnovm/tests/files/heap_alloc_forloop4.gno | 31 + gnovm/tests/files/heap_alloc_forloop5.gno | 32 + gnovm/tests/files/heap_alloc_forloop5a.gno | 33 + gnovm/tests/files/heap_alloc_forloop6.gno | 25 + gnovm/tests/files/heap_alloc_forloop6a.gno | 26 + gnovm/tests/files/heap_alloc_forloop6b.gno | 25 + gnovm/tests/files/heap_alloc_forloop6c.gno | 23 + gnovm/tests/files/heap_alloc_forloop6f.gno | 26 + gnovm/tests/files/heap_alloc_forloop6g.gno | 27 + gnovm/tests/files/heap_alloc_forloop6h.gno | 33 + gnovm/tests/files/heap_alloc_forloop6h0.gno | 27 + gnovm/tests/files/heap_alloc_forloop6i.gno | 34 + gnovm/tests/files/heap_alloc_forloop7.gno | 28 + gnovm/tests/files/heap_alloc_forloop7a.gno | 26 + gnovm/tests/files/heap_alloc_forloop8.gno | 25 + gnovm/tests/files/heap_alloc_forloop8a.gno | 26 + gnovm/tests/files/heap_alloc_forloop8b.gno | 28 + gnovm/tests/files/heap_alloc_forloop8c.gno | 30 + gnovm/tests/files/heap_alloc_forloop9.gno | 42 + gnovm/tests/files/heap_alloc_forloop9_1.gno | 25 + gnovm/tests/files/heap_alloc_forloop9_2.gno | 36 + gnovm/tests/files/heap_alloc_forloop9b.gno | 28 + gnovm/tests/files/heap_alloc_gotoloop0.gno | 28 + gnovm/tests/files/heap_alloc_gotoloop1.gno | 30 + gnovm/tests/files/heap_alloc_gotoloop2.gno | 37 + gnovm/tests/files/heap_alloc_gotoloop3.gno | 34 + gnovm/tests/files/heap_alloc_gotoloop4.gno | 34 + gnovm/tests/files/heap_alloc_gotoloop5.gno | 39 + gnovm/tests/files/heap_alloc_gotoloop6.gno | 39 + gnovm/tests/files/heap_alloc_gotoloop7.gno | 48 ++ gnovm/tests/files/heap_alloc_gotoloop8.gno | 37 + gnovm/tests/files/heap_alloc_gotoloop9.gno | 35 + gnovm/tests/files/heap_alloc_gotoloop9_10.gno | 64 ++ gnovm/tests/files/heap_alloc_gotoloop9_11.gno | 29 + gnovm/tests/files/heap_alloc_gotoloop9_12.gno | 56 ++ gnovm/tests/files/heap_alloc_gotoloop9_13.gno | 41 + gnovm/tests/files/heap_alloc_gotoloop9_14.gno | 43 + gnovm/tests/files/heap_alloc_gotoloop9_15.gno | 48 ++ .../tests/files/heap_alloc_gotoloop9_15a.gno | 46 + gnovm/tests/files/heap_alloc_gotoloop9_16.gno | 58 ++ gnovm/tests/files/heap_alloc_gotoloop9_17.gno | 58 ++ gnovm/tests/files/heap_alloc_gotoloop9_18.gno | 30 + gnovm/tests/files/heap_alloc_gotoloop9_19.gno | 30 + gnovm/tests/files/heap_alloc_gotoloop9_20.gno | 32 + gnovm/tests/files/heap_alloc_gotoloop9_21.gno | 31 + .../tests/files/heap_alloc_gotoloop9_21a.gno | 33 + .../tests/files/heap_alloc_gotoloop9_21b.gno | 34 + gnovm/tests/files/heap_alloc_gotoloop9_22.gno | 33 + gnovm/tests/files/heap_alloc_range1.gno | 30 + gnovm/tests/files/heap_alloc_range2.gno | 30 + gnovm/tests/files/heap_alloc_range3.gno | 23 + gnovm/tests/files/heap_alloc_range4.gno | 24 + gnovm/tests/files/heap_alloc_range4a.gno | 26 + gnovm/tests/files/heap_alloc_range4a1.gno | 22 + gnovm/tests/files/heap_alloc_range4a2.gno | 32 + gnovm/tests/files/heap_alloc_range4b.gno | 26 + gnovm/tests/files/heap_alloc_range4b1.gno | 25 + gnovm/tests/files/import6.gno | 2 +- gnovm/tests/files/recursive1.gno | 2 +- gnovm/tests/files/recursive1c.gno | 2 +- gnovm/tests/files/recursive1d.gno | 2 +- gnovm/tests/files/recursive1f.gno | 2 +- gnovm/tests/files/recursive2.gno | 2 +- gnovm/tests/files/recursive2c.gno | 2 +- gnovm/tests/files/recursive4a.gno | 2 +- gnovm/tests/files/recursive5.gno | 2 +- gnovm/tests/files/recursive6a.gno | 2 +- gnovm/tests/files/recursive7a.gno | 2 +- gnovm/tests/files/recursive8.gno | 2 +- gnovm/tests/files/recursive9.gno | 2 +- gnovm/tests/files/recursive9a.gno | 2 +- gnovm/tests/files/recursive9b.gno | 2 +- gnovm/tests/files/recursive9c.gno | 2 +- gnovm/tests/files/recursive9d.gno | 2 +- gnovm/tests/files/switch13.gno | 2 +- gnovm/tests/files/types/assign_literal11.gno | 2 +- gnovm/tests/files/types/assign_literal3.gno | 2 +- gnovm/tests/files/types/assign_nil.gno | 2 +- gnovm/tests/files/types/assign_nil2.gno | 2 +- gnovm/tests/files/var18.gno | 2 +- gnovm/tests/files/var19.gno | 5 +- gnovm/tests/files/var22.gno | 2 +- 116 files changed, 3343 insertions(+), 354 deletions(-) create mode 100644 gnovm/tests/files/heap_alloc_defer.gno create mode 100644 gnovm/tests/files/heap_alloc_defer2.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop1.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop1a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop1b.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop2.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop2a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop3.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop3a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop4.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop5.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop5a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6b.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6c.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6f.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6g.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6h.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6h0.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop6i.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop7.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop7a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop8.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop8a.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop8b.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop8c.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop9.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop9_1.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop9_2.gno create mode 100644 gnovm/tests/files/heap_alloc_forloop9b.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop0.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop1.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop2.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop3.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop4.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop5.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop6.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop7.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop8.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_10.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_11.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_12.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_13.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_14.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_15.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_15a.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_16.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_17.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_18.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_19.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_20.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_21.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_21a.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_21b.gno create mode 100644 gnovm/tests/files/heap_alloc_gotoloop9_22.gno create mode 100644 gnovm/tests/files/heap_alloc_range1.gno create mode 100644 gnovm/tests/files/heap_alloc_range2.gno create mode 100644 gnovm/tests/files/heap_alloc_range3.gno create mode 100644 gnovm/tests/files/heap_alloc_range4.gno create mode 100644 gnovm/tests/files/heap_alloc_range4a.gno create mode 100644 gnovm/tests/files/heap_alloc_range4a1.gno create mode 100644 gnovm/tests/files/heap_alloc_range4a2.gno create mode 100644 gnovm/tests/files/heap_alloc_range4b.gno create mode 100644 gnovm/tests/files/heap_alloc_range4b1.gno diff --git a/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar b/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar index 0954d1dd9327..6099788a9a10 100644 --- a/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar @@ -4,7 +4,7 @@ ! stdout .+ stderr 'panic: unknown import path net \[recovered\]' -stderr ' panic: gno.land/r/\w{8}/contract.gno:3:1: unknown import path net' +stderr ' panic: gno.land/r/\w{8}/contract.gno:3:8: unknown import path net' gno test -v --with-native-fallback . diff --git a/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar b/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar index 15125f695f53..37ef68f3d911 100644 --- a/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar @@ -4,13 +4,13 @@ ! stdout .+ stderr 'panic: unknown import path foobarbaz \[recovered\]' -stderr ' panic: gno.land/r/\w{8}/contract.gno:3:1: unknown import path foobarbaz' +stderr ' panic: gno.land/r/\w{8}/contract.gno:3:8: unknown import path foobarbaz' ! gno test -v --with-native-fallback . ! stdout .+ stderr 'panic: unknown import path foobarbaz \[recovered\]' -stderr ' panic: gno.land/r/\w{8}/contract.gno:3:1: unknown import path foobarbaz' +stderr ' panic: gno.land/r/\w{8}/contract.gno:3:8: unknown import path foobarbaz' -- contract.gno -- package contract diff --git a/gnovm/pkg/gnolang/debugger.go b/gnovm/pkg/gnolang/debugger.go index 839b6a691de1..f047a176af73 100644 --- a/gnovm/pkg/gnolang/debugger.go +++ b/gnovm/pkg/gnolang/debugger.go @@ -257,8 +257,10 @@ func debugUpdateLocation(m *Machine) { for i := nx - 1; i >= 0; i-- { expr := m.Exprs[i] if l := expr.GetLine(); l > 0 { - m.Debugger.loc.Line = l - m.Debugger.loc.Column = expr.GetColumn() + if col := expr.GetColumn(); col > 0 { + m.Debugger.loc.Line = l + m.Debugger.loc.Column = expr.GetColumn() + } return } } @@ -266,8 +268,10 @@ func debugUpdateLocation(m *Machine) { if len(m.Stmts) > 0 { if stmt := m.PeekStmt1(); stmt != nil { if l := stmt.GetLine(); l > 0 { - m.Debugger.loc.Line = l - m.Debugger.loc.Column = stmt.GetColumn() + if col := stmt.GetColumn(); col > 0 { + m.Debugger.loc.Line = l + m.Debugger.loc.Column = stmt.GetColumn() + } return } } @@ -648,7 +652,7 @@ func debugEvalExpr(m *Machine, node ast.Node) (tv TypedValue, err error) { return tv, fmt.Errorf("invalid selector: %s", n.Sel.Name) } for _, vp := range tr { - x = x.GetPointerTo(m.Alloc, m.Store, vp).Deref() + x = x.GetPointerToFromTV(m.Alloc, m.Store, vp).Deref() } return x, nil case *ast.IndexExpr: diff --git a/gnovm/pkg/gnolang/debugger_test.go b/gnovm/pkg/gnolang/debugger_test.go index fe059ba9f56c..44786257d671 100644 --- a/gnovm/pkg/gnolang/debugger_test.go +++ b/gnovm/pkg/gnolang/debugger_test.go @@ -131,7 +131,7 @@ func TestDebug(t *testing.T) { {in: "p \"xxxx\"\n", out: `("xxxx" string)`}, {in: "si\n", out: "sample.gno:14"}, {in: "s\ns\n", out: `=> 14: var global = "test"`}, - {in: "s\n\n", out: "=> 33: num := 5"}, + {in: "s\n\n\n", out: "=> 33: num := 5"}, {in: "foo", out: "command not available: foo"}, {in: "\n\n", out: "dbg> "}, {in: "#\n", out: "dbg> "}, diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index efdfecf02897..6bde6fb5271e 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -754,11 +754,13 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { name := toName(s.Name) tipe := toExpr(fs, s.Type) alias := s.Assign != 0 - ds = append(ds, &TypeDecl{ + td := &TypeDecl{ NameExpr: NameExpr{Name: name}, Type: tipe, IsAlias: alias, - }) + } + setLoc(fs, s.Pos(), td) + ds = append(ds, td) case *ast.ValueSpec: if gd.Tok == token.CONST { var names []NameExpr diff --git a/gnovm/pkg/gnolang/kind_string.go b/gnovm/pkg/gnolang/kind_string.go index cbe6bfa8e339..12e95829b207 100644 --- a/gnovm/pkg/gnolang/kind_string.go +++ b/gnovm/pkg/gnolang/kind_string.go @@ -36,13 +36,14 @@ func _() { _ = x[MapKind-25] _ = x[TypeKind-26] _ = x[BlockKind-27] - _ = x[TupleKind-28] - _ = x[RefTypeKind-29] + _ = x[HeapItemKind-28] + _ = x[TupleKind-29] + _ = x[RefTypeKind-30] } -const _Kind_name = "InvalidKindBoolKindStringKindIntKindInt8KindInt16KindInt32KindInt64KindUintKindUint8KindUint16KindUint32KindUint64KindFloat32KindFloat64KindBigintKindBigdecKindArrayKindSliceKindPointerKindStructKindPackageKindInterfaceKindChanKindFuncKindMapKindTypeKindBlockKindTupleKindRefTypeKind" +const _Kind_name = "InvalidKindBoolKindStringKindIntKindInt8KindInt16KindInt32KindInt64KindUintKindUint8KindUint16KindUint32KindUint64KindFloat32KindFloat64KindBigintKindBigdecKindArrayKindSliceKindPointerKindStructKindPackageKindInterfaceKindChanKindFuncKindMapKindTypeKindBlockKindHeapItemKindTupleKindRefTypeKind" -var _Kind_index = [...]uint16{0, 11, 19, 29, 36, 44, 53, 62, 71, 79, 88, 98, 108, 118, 129, 140, 150, 160, 169, 178, 189, 199, 210, 223, 231, 239, 246, 254, 263, 272, 283} +var _Kind_index = [...]uint16{0, 11, 19, 29, 36, 44, 53, 62, 71, 79, 88, 98, 108, 118, 129, 140, 150, 160, 169, 178, 189, 199, 210, 223, 231, 239, 246, 254, 263, 275, 284, 295} func (i Kind) String() string { if i >= Kind(len(_Kind_index)-1) { diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index ad94f1a2b3a5..1e594de945bd 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -699,7 +699,7 @@ func (m *Machine) runFileDecls(fns ...*FileNode) []TypedValue { } } // if dep already in loopfindr, abort. - if hasName(dep, loopfindr) { + if slices.Contains(loopfindr, dep) { if _, ok := (*depdecl).(*FuncDecl); ok { // recursive function dependencies // are OK with func decls. @@ -2112,15 +2112,25 @@ func (m *Machine) PushForPointer(lx Expr) { func (m *Machine) PopAsPointer(lx Expr) PointerValue { switch lx := lx.(type) { case *NameExpr: - lb := m.LastBlock() - return lb.GetPointerTo(m.Store, lx.Path) + switch lx.Type { + case NameExprTypeNormal: + lb := m.LastBlock() + return lb.GetPointerTo(m.Store, lx.Path) + case NameExprTypeHeapUse: + lb := m.LastBlock() + return lb.GetPointerToHeapUse(m.Store, lx.Path) + case NameExprTypeHeapClosure: + panic("should not happen") + default: + panic("unexpected NameExpr in PopAsPointer") + } case *IndexExpr: iv := m.PopValue() xv := m.PopValue() return xv.GetPointerAtIndex(m.Alloc, m.Store, iv) case *SelectorExpr: xv := m.PopValue() - return xv.GetPointerTo(m.Alloc, m.Store, lx.Path) + return xv.GetPointerToFromTV(m.Alloc, m.Store, lx.Path) case *StarExpr: ptr := m.PopValue().V.(PointerValue) return ptr @@ -2348,15 +2358,3 @@ func (m *Machine) ExceptionsStacktrace() string { return builder.String() } - -//---------------------------------------- -// utility - -func hasName(n Name, ns []Name) bool { - for _, n2 := range ns { - if n == n2 { - return true - } - } - return false -} diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index f1bd78ee646b..9e7cea8fb7f3 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -146,11 +146,26 @@ func (loc Location) IsZero() bool { // even after preprocessing. Temporary attributes (e.g. those // for preprocessing) are stored in .data. +type GnoAttribute string + +const ( + ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED" + ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED" + ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE" + ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE" + ATTR_IOTA GnoAttribute = "ATTR_IOTA" + ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONE" // XXX DELETE + ATTR_GOTOLOOP_STMT GnoAttribute = "ATTR_GOTOLOOP_STMT" // XXX delete? + ATTR_LOOP_DEFINES GnoAttribute = "ATTR_LOOP_DEFINES" // []Name defined within loops. + ATTR_LOOP_USES GnoAttribute = "ATTR_LOOP_USES" // []Name loop defines actually used. + ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS" +) + type Attributes struct { Line int Column int Label Name - data map[interface{}]interface{} // not persisted + data map[GnoAttribute]interface{} // not persisted } func (attr *Attributes) GetLine() int { @@ -177,22 +192,31 @@ func (attr *Attributes) SetLabel(label Name) { attr.Label = label } -func (attr *Attributes) HasAttribute(key interface{}) bool { +func (attr *Attributes) HasAttribute(key GnoAttribute) bool { _, ok := attr.data[key] return ok } -func (attr *Attributes) GetAttribute(key interface{}) interface{} { +// GnoAttribute must not be user provided / arbitrary, +// otherwise will create potential exploits. +func (attr *Attributes) GetAttribute(key GnoAttribute) interface{} { return attr.data[key] } -func (attr *Attributes) SetAttribute(key interface{}, value interface{}) { +func (attr *Attributes) SetAttribute(key GnoAttribute, value interface{}) { if attr.data == nil { - attr.data = make(map[interface{}]interface{}) + attr.data = make(map[GnoAttribute]interface{}) } attr.data[key] = value } +func (attr *Attributes) DelAttribute(key GnoAttribute) { + if debug && attr.data == nil { + panic("should not happen, attribute is expected to be non-empty.") + } + delete(attr.data, key) +} + // ---------------------------------------- // Node @@ -206,9 +230,10 @@ type Node interface { SetColumn(int) GetLabel() Name SetLabel(Name) - HasAttribute(key interface{}) bool - GetAttribute(key interface{}) interface{} - SetAttribute(key interface{}, value interface{}) + HasAttribute(key GnoAttribute) bool + GetAttribute(key GnoAttribute) interface{} + SetAttribute(key GnoAttribute, value interface{}) + DelAttribute(key GnoAttribute) } // non-pointer receiver to help make immutable. @@ -368,11 +393,22 @@ var ( _ Expr = &ConstExpr{} ) +type NameExprType int + +const ( + NameExprTypeNormal NameExprType = iota // default + NameExprTypeDefine // when defining normally + NameExprTypeHeapDefine // when defining escaped name in loop + NameExprTypeHeapUse // when above used in non-define lhs/rhs + NameExprTypeHeapClosure // when closure captures name +) + type NameExpr struct { Attributes // TODO rename .Path's to .ValuePaths. Path ValuePath // set by preprocessor. Name + Type NameExprType } type NameExprs []NameExpr @@ -499,8 +535,9 @@ type KeyValueExprs []KeyValueExpr type FuncLitExpr struct { Attributes StaticBlock - Type FuncTypeExpr // function type - Body // function body + Type FuncTypeExpr // function type + Body // function body + HeapCaptures NameExprs // filled in findLoopUses1 } // The preprocessor replaces const expressions @@ -581,11 +618,15 @@ func (ftxz FieldTypeExprs) IsNamed() bool { named := false for i, ftx := range ftxz { if i == 0 { - named = ftx.Name != "" + if ftx.Name == "" || isHiddenResultVariable(string(ftx.Name)) { + named = false + } else { + named = true + } } else { if named && ftx.Name == "" { panic("[]FieldTypeExpr has inconsistent namedness (starts named)") - } else if !named && ftx.Name != "" { + } else if !named && (ftx.Name != "" || !isHiddenResultVariable(string(ftx.Name))) { panic("[]FieldTypeExpr has inconsistent namedness (starts unnamed)") } } @@ -1489,6 +1530,7 @@ type BlockNode interface { GetNumNames() uint16 GetParentNode(Store) BlockNode GetPathForName(Store, Name) ValuePath + GetBlockNodeForPath(Store, ValuePath) BlockNode GetIsConst(Store, Name) bool GetLocalIndex(Name) (uint16, bool) GetValueRef(Store, Name, bool) *TypedValue @@ -1588,6 +1630,8 @@ func (sb *StaticBlock) GetBlockNames() (ns []Name) { } // Implements BlockNode. +// NOTE: Extern names may also be local, if declared after usage as an extern +// (thus shadowing the extern name). func (sb *StaticBlock) GetExternNames() (ns []Name) { return sb.Externs // copy? } @@ -1629,6 +1673,9 @@ func (sb *StaticBlock) GetPathForName(store Store, n Name) ValuePath { } // Register as extern. // NOTE: uverse names are externs too. + // NOTE: externs may also be shadowed later in the block. Thus, usages + // before the declaration will have depth > 1; following it, depth == 1, + // matching the two different identifiers they refer to. if !isFile(sb.GetSource(store)) { sb.GetStaticBlock().addExternName(n) } @@ -1657,6 +1704,21 @@ func (sb *StaticBlock) GetPathForName(store Store, n Name) ValuePath { panic(fmt.Sprintf("name %s not declared", n)) } +// Get the containing block node for node with path relative to this containing block. +func (sb *StaticBlock) GetBlockNodeForPath(store Store, path ValuePath) BlockNode { + if path.Type != VPBlock { + panic("expected block type value path but got " + path.Type.String()) + } + + // NOTE: path.Depth == 1 means it's in bn. + bn := sb.GetSource(store) + for i := 1; i < int(path.Depth); i++ { + bn = bn.GetParentNode(store) + } + + return bn +} + // Returns whether a name defined here in in ancestry is a const. // This is not the same as whether a name's static type is // untyped -- as in c := a == b, a name may be an untyped non-const. @@ -1713,21 +1775,12 @@ func (sb *StaticBlock) GetStaticTypeOf(store Store, n Name) Type { // Implements BlockNode. func (sb *StaticBlock) GetStaticTypeOfAt(store Store, path ValuePath) Type { if debug { - if path.Type != VPBlock { - panic("should not happen") - } if path.Depth == 0 { panic("should not happen") } } - for { - if path.Depth == 1 { - return sb.Types[path.Index] - } else { - sb = sb.GetParentNode(store).GetStaticBlock() - path.Depth -= 1 - } - } + bn := sb.GetBlockNodeForPath(store, path) + return bn.GetStaticBlock().Types[path.Index] } // Implements BlockNode. @@ -2115,18 +2168,6 @@ func (x *BasicLitExpr) GetInt() int { return i } -type GnoAttribute string - -const ( - ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED" - ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED" - ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE" - ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE" - ATTR_IOTA GnoAttribute = "ATTR_IOTA" - ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" - ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS" -) - var rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]+$`) // TODO: consider length restrictions. @@ -2136,3 +2177,12 @@ func validatePkgName(name string) { panic(fmt.Sprintf("cannot create package with invalid name %q", name)) } } + +const hiddenResultVariable = ".res_" + +func isHiddenResultVariable(name string) bool { + if strings.HasPrefix(name, hiddenResultVariable) { + return true + } + return false +} diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index 547ad83294dd..e16e2f182a58 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -96,7 +96,20 @@ func (vp ValuePath) String() string { } func (x NameExpr) String() string { - return fmt.Sprintf("%s<%s>", x.Name, x.Path.String()) + switch x.Type { + case NameExprTypeNormal: + return fmt.Sprintf("%s<%s>", x.Name, x.Path.String()) + case NameExprTypeDefine: + return fmt.Sprintf("%s", x.Name, x.Path.String()) + case NameExprTypeHeapDefine: + return fmt.Sprintf("%s", x.Name, x.Path.String()) + case NameExprTypeHeapUse: + return fmt.Sprintf("%s<~%s>", x.Name, x.Path.String()) + case NameExprTypeHeapClosure: + return fmt.Sprintf("%s<()~%s>", x.Name, x.Path.String()) + default: + panic("unexpected NameExpr type") + } } func (x BasicLitExpr) String() string { @@ -172,7 +185,11 @@ func (x CompositeLitExpr) String() string { } func (x FuncLitExpr) String() string { - return fmt.Sprintf("func %s{ %s }", x.Type, x.Body.String()) + heapCaptures := "" + if len(x.HeapCaptures) > 0 { + heapCaptures = "<" + x.HeapCaptures.String() + ">" + } + return fmt.Sprintf("func %s{ %s }%s", x.Type, x.Body.String(), heapCaptures) } func (x KeyValueExpr) String() string { diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index eb67ffcc3512..8caacbfd1e62 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -11,7 +11,7 @@ func (m *Machine) doOpDefine() { // Get name and value of i'th term. nx := s.Lhs[i].(*NameExpr) // Finally, define (or assign if loop block). - ptr := lb.GetPointerTo(m.Store, nx.Path) + ptr := lb.GetPointerToMaybeHeapDefine(m.Store, nx) // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := ptr.Base.(Object); ok { diff --git a/gnovm/pkg/gnolang/op_call.go b/gnovm/pkg/gnolang/op_call.go index 510c308a86a8..ba5b7507cff1 100644 --- a/gnovm/pkg/gnolang/op_call.go +++ b/gnovm/pkg/gnolang/op_call.go @@ -62,6 +62,18 @@ func (m *Machine) doOpCall() { // Create new block scope. clo := fr.Func.GetClosure(m.Store) b := m.Alloc.NewBlock(fr.Func.GetSource(m.Store), clo) + + // Copy *FuncValue.Captures into block + // NOTE: addHeapCapture in preprocess ensures order. + if len(fv.Captures) != 0 { + if len(fv.Captures) > len(b.Values) { + panic("should not happen, length of captured variables must not exceed the number of values") + } + for i := 0; i < len(fv.Captures); i++ { + b.Values[len(b.Values)-len(fv.Captures)+i] = fv.Captures[i].Copy(m.Alloc) + } + } + m.PushBlock(b) if fv.nativeBody == nil && fv.NativePkg != "" { // native function, unmarshaled so doesn't have nativeBody yet @@ -83,6 +95,7 @@ func (m *Machine) doOpCall() { // Initialize return variables with default value. numParams := len(ft.Params) for i, rt := range ft.Results { + // results/parameters never are heap use/closure. ptr := b.GetPointerToInt(nil, numParams+i) dtv := defaultTypedValue(m.Alloc, rt.Type) ptr.Assign2(m.Alloc, nil, nil, dtv, false) @@ -292,6 +305,15 @@ func (m *Machine) doOpReturnCallDefers() { // Create new block scope for defer. clo := dfr.Func.GetClosure(m.Store) b := m.Alloc.NewBlock(fv.GetSource(m.Store), clo) + // copy values from captures + if len(fv.Captures) != 0 { + if len(fv.Captures) > len(b.Values) { + panic("should not happen, length of captured variables must not exceed the number of values") + } + for i := 0; i < len(fv.Captures); i++ { + b.Values[len(b.Values)-len(fv.Captures)+i] = fv.Captures[i].Copy(m.Alloc) + } + } m.PushBlock(b) if fv.nativeBody == nil { fbody := fv.GetBodyFromSource(m.Store) diff --git a/gnovm/pkg/gnolang/op_decl.go b/gnovm/pkg/gnolang/op_decl.go index 2c20c43ae2f9..c9c04ccf76d9 100644 --- a/gnovm/pkg/gnolang/op_decl.go +++ b/gnovm/pkg/gnolang/op_decl.go @@ -58,8 +58,8 @@ func (m *Machine) doOpValueDecl() { } else if isUntyped(tv.T) { ConvertUntypedTo(&tv, nil) } - nx := s.NameExprs[i] - ptr := lb.GetPointerTo(m.Store, nx.Path) + nx := &s.NameExprs[i] + ptr := lb.GetPointerToMaybeHeapDefine(m.Store, nx) ptr.Assign2(m.Alloc, m.Store, m.Realm, tv, false) } } diff --git a/gnovm/pkg/gnolang/op_eval.go b/gnovm/pkg/gnolang/op_eval.go index 701615fff134..1beba1d6e3f0 100644 --- a/gnovm/pkg/gnolang/op_eval.go +++ b/gnovm/pkg/gnolang/op_eval.go @@ -36,7 +36,7 @@ func (m *Machine) doOpEval() { // Get value from scope. lb := m.LastBlock() // Push value, done. - ptr := lb.GetPointerTo(m.Store, nx.Path) + ptr := lb.GetPointerToMaybeHeapUse(m.Store, nx) m.PushValue(ptr.Deref()) return } diff --git a/gnovm/pkg/gnolang/op_exec.go b/gnovm/pkg/gnolang/op_exec.go index c7e8ffd600c0..a61349b08069 100644 --- a/gnovm/pkg/gnolang/op_exec.go +++ b/gnovm/pkg/gnolang/op_exec.go @@ -171,8 +171,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Key).Assign2(m.Alloc, m.Store, m.Realm, iv, false) case DEFINE: - knxp := bs.Key.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, knxp) + knx := bs.Key.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, knx) ptr.TV.Assign(m.Alloc, iv, false) default: panic("should not happen") @@ -186,8 +186,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Value).Assign2(m.Alloc, m.Store, m.Realm, ev, false) case DEFINE: - vnxp := bs.Value.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, vnxp) + vnx := bs.Value.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, vnx) ptr.TV.Assign(m.Alloc, ev, false) default: panic("should not happen") @@ -267,8 +267,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Key).Assign2(m.Alloc, m.Store, m.Realm, iv, false) case DEFINE: - knxp := bs.Key.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, knxp) + knx := bs.Key.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, knx) ptr.TV.Assign(m.Alloc, iv, false) default: panic("should not happen") @@ -280,8 +280,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Value).Assign2(m.Alloc, m.Store, m.Realm, ev, false) case DEFINE: - vnxp := bs.Value.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, vnxp) + vnx := bs.Value.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, vnx) ptr.TV.Assign(m.Alloc, ev, false) default: panic("should not happen") @@ -360,8 +360,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Key).Assign2(m.Alloc, m.Store, m.Realm, kv, false) case DEFINE: - knxp := bs.Key.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, knxp) + knx := bs.Key.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, knx) ptr.TV.Assign(m.Alloc, kv, false) default: panic("should not happen") @@ -373,8 +373,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Value).Assign2(m.Alloc, m.Store, m.Realm, vv, false) case DEFINE: - vnxp := bs.Value.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, vnxp) + vnx := bs.Value.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, vnx) ptr.TV.Assign(m.Alloc, vv, false) default: panic("should not happen") @@ -884,6 +884,8 @@ func (m *Machine) doOpTypeSwitch() { // NOTE: assumes the var is first in block. vp := NewValuePath( VPBlock, 1, 0, ss.VarName) + // NOTE: GetPointerToMaybeHeapDefine not needed, + // because this type is in new type switch clause block. ptr := b.GetPointerTo(m.Store, vp) ptr.TV.Assign(m.Alloc, *xv, false) } diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 8ff0b5bd538d..a1d677ca8788 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -78,7 +78,7 @@ func (m *Machine) doOpIndex2() { func (m *Machine) doOpSelector() { sx := m.PopExpr().(*SelectorExpr) xv := m.PeekValue(1) - res := xv.GetPointerTo(m.Alloc, m.Store, sx.Path).Deref() + res := xv.GetPointerToFromTV(m.Alloc, m.Store, sx.Path).Deref() if debug { m.Printf("-v[S] %v\n", xv) m.Printf("+v[S] %v\n", res) @@ -758,6 +758,25 @@ func (m *Machine) doOpFuncLit() { ft := m.PopValue().V.(TypeValue).Type.(*FuncType) lb := m.LastBlock() m.Alloc.AllocateFunc() + + // First copy closure captured heap values + // to *FuncValue. Later during doOpCall a block + // will be created that copies these values for + // every invocation of the function. + captures := []TypedValue(nil) + for _, nx := range x.HeapCaptures { + ptr := lb.GetPointerTo(m.Store, nx.Path) + // check that ptr.TV is a heap item value. + // it must be in the form of: + // {T:heapItemType{},V:HeapItemValue{...}} + if _, ok := ptr.TV.T.(heapItemType); !ok { + panic("should not happen, should be heapItemType") + } + if _, ok := ptr.TV.V.(*HeapItemValue); !ok { + panic("should not happen, should be heapItemValue") + } + captures = append(captures, *ptr.TV) + } m.PushValue(TypedValue{ T: ft, V: &FuncValue{ @@ -766,6 +785,7 @@ func (m *Machine) doOpFuncLit() { Source: x, Name: "", Closure: lb, + Captures: captures, PkgPath: m.Package.PkgPath, body: x.Body, nativeBody: nil, diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 757cbbae3170..e1dc3671333a 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,8 +2,10 @@ package gnolang import ( "fmt" + "math" "math/big" "reflect" + "slices" "strings" "sync/atomic" @@ -23,7 +25,8 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // This will also reserve names on BlockNode.StaticBlock by // calling StaticBlock.Predefine(). for _, fn := range fset.Files { - SetNodeLocations(pn.PkgPath, string(fn.Name), fn) + setNodeLines(fn) + setNodeLocations(pn.PkgPath, string(fn.Name), fn) initStaticBlocks(store, pn, fn) } // NOTE: The calls to .Predefine() above is more of a name reservation, @@ -92,7 +95,7 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } } } - // Finally, predefine other decls and + // Then, predefine other decls and // preprocess ValueDecls.. for _, fn := range fset.Files { for i := 0; i < len(fn.Decls); i++ { @@ -143,32 +146,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { // iterate over all nodes recursively. _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { - defer func() { - if r := recover(); r != nil { - // before re-throwing the error, append location information to message. - loc := last.GetLocation() - if nline := n.GetLine(); nline > 0 { - loc.Line = nline - } - - var err error - rerr, ok := r.(error) - if ok { - // NOTE: gotuna/gorilla expects error exceptions. - err = errors.Wrap(rerr, loc.String()) - } else { - // NOTE: gotuna/gorilla expects error exceptions. - err = fmt.Errorf("%s: %v", loc.String(), r) - } - - // Re-throw the error after wrapping it with the preprocessing stack information. - panic(&PreprocessError{ - err: err, - stack: stack, - }) - } - }() - + defer doRecover(stack, n) if debug { debug.Printf("initStaticBlocks %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } @@ -181,45 +159,57 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { if n.Op == DEFINE { var defined bool for _, lx := range n.Lhs { - ln := lx.(*NameExpr).Name + nx := lx.(*NameExpr) + ln := nx.Name if ln == blankIdentifier { continue } - last.Predefine(false, ln) - defined = true + if !isLocallyDefined2(last, ln) { + // if loop extern, will change to + // NameExprTypeHeapDefine later. + nx.Type = NameExprTypeDefine + last.Predefine(false, ln) + defined = true + } } if !defined { panic(fmt.Sprintf("nothing defined in assignment %s", n.String())) } } case *ImportDecl: - name := n.Name - if name == "." { + nx := &n.NameExpr + nn := nx.Name + if nn == "." { panic("dot imports not allowed in gno") } - if name == "" { // use default + if nn == "" { // use default pv := store.GetPackage(n.PkgPath, true) if pv == nil { panic(fmt.Sprintf( "unknown import path %s", n.PkgPath)) } - name = pv.PkgName + nn = pv.PkgName } - if name != blankIdentifier { - last.Predefine(false, name) + if nn != blankIdentifier { + nx.Type = NameExprTypeDefine + last.Predefine(false, nn) } case *ValueDecl: last2 := skipFile(last) for i := 0; i < len(n.NameExprs); i++ { nx := &n.NameExprs[i] - if nx.Name == blankIdentifier { + nn := nx.Name + if nn == blankIdentifier { continue } - last2.Predefine(n.Const, nx.Name) + nx.Type = NameExprTypeDefine + last2.Predefine(n.Const, nn) } case *TypeDecl: last2 := skipFile(last) + nx := &n.NameExpr + nx.Type = NameExprTypeDefine last2.Predefine(false, n.Name) case *FuncDecl: if n.IsMethod { @@ -238,7 +228,8 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { dname := Name(fmt.Sprintf("init.%d", idx)) n.Name = dname } - + nx := &n.NameExpr + nx.Type = NameExprTypeDefine pkg.Predefine(false, n.Name) } case *FuncTypeExpr: @@ -256,7 +247,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { if r.Name == blankIdentifier { // create a hidden var with leading dot. // NOTE: document somewhere. - rn := fmt.Sprintf(".res_%d", i) + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) r.Name = Name(rn) } } @@ -265,15 +256,9 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { // ---------------------------------------- case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) switch n := n.(type) { - case *BlockStmt: - pushInitBlock(n, &last, &stack) - case *ForStmt: - pushInitBlock(n, &last, &stack) - case *IfStmt: - pushInitBlock(n, &last, &stack) case *IfCaseStmt: - pushInitRealBlock(n, &last, &stack) // parent if statement. ifs := ns[len(ns)-1].(*IfStmt) // anything declared in ifs are copied. @@ -281,17 +266,27 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { last.Predefine(false, n) } case *RangeStmt: - pushInitBlock(n, &last, &stack) if n.Op == DEFINE { if n.Key != nil { - last.Predefine(false, n.Key.(*NameExpr).Name) + nx := n.Key.(*NameExpr) + if nx.Name != blankIdentifier { + // XXX, this should be uncommented when fully + // support Go1.22 loopvar, to make it consistent + // with for i := 0; i < 10; i++ {...}. + // nx.Type = NameExprTypeDefine + + last.Predefine(false, nx.Name) + } } if n.Value != nil { - last.Predefine(false, n.Value.(*NameExpr).Name) + nx := n.Value.(*NameExpr) + if nx.Name != blankIdentifier { + // nx.Type = NameExprTypeDefine // XXX,ditto + last.Predefine(false, nx.Name) + } } } case *FuncLitExpr: - pushInitBlock(n, &last, &stack) for _, p := range n.Type.Params { last.Predefine(false, p.Name) } @@ -300,10 +295,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { last.Predefine(false, rf.Name) } } - case *SelectCaseStmt: - pushInitBlock(n, &last, &stack) case *SwitchStmt: - pushInitBlock(n, &last, &stack) if n.VarName != "" { // NOTE: this defines for default clauses too, // see comment on block copying @ @@ -311,7 +303,6 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { last.Predefine(false, n.VarName) } case *SwitchClauseStmt: - pushInitRealBlock(n, &last, &stack) // parent switch statement. ss := ns[len(ns)-1].(*SwitchStmt) // anything declared in ss are copied, @@ -329,7 +320,6 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { } } case *FuncDecl: - pushInitBlock(n, &last, &stack) if n.IsMethod { n.Predefine(false, n.Recv.Name) } @@ -339,23 +329,24 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { } n.Predefine(false, pte.Name) } - for _, rte := range n.Type.Results { - if rte.Name != "" { - n.Predefine(false, rte.Name) + for i, rte := range n.Type.Results { + if rte.Name == "" { + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) + rte.Name = Name(rn) } + n.Predefine(false, rte.Name) } - case *FileNode: - pushInitBlock(n, &last, &stack) - default: - panic("should not happen") } return n, TRANS_CONTINUE // ---------------------------------------- case TRANS_LEAVE: - // finalization. - if _, ok := n.(BlockNode); ok { - // Pop block. + // Pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + switch n.(type) { + case BlockNode: stack = stack[:len(stack)-1] last = stack[len(stack)-1] } @@ -365,6 +356,34 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { }) } +func doRecover(stack []BlockNode, n Node) { + if r := recover(); r != nil { + // before re-throwing the error, append location information to message. + last := stack[len(stack)-1] + loc := last.GetLocation() + if nline := n.GetLine(); nline > 0 { + loc.Line = nline + loc.Column = n.GetColumn() + } + + var err error + rerr, ok := r.(error) + if ok { + // NOTE: gotuna/gorilla expects error exceptions. + err = errors.Wrap(rerr, loc.String()) + } else { + // NOTE: gotuna/gorilla expects error exceptions. + err = fmt.Errorf("%s: %v", loc.String(), r) + } + + // Re-throw the error after wrapping it with the preprocessing stack information. + panic(&PreprocessError{ + err: err, + stack: stack, + }) + } +} + // This counter ensures (during testing) that certain functions // (like ConvertUntypedTo() for bigints and strings) // are only called during the preprocessing stage. @@ -390,6 +409,27 @@ var preprocessing atomic.Int32 // - Assigns BlockValuePath to NameExprs. // - TODO document what it does. func Preprocess(store Store, ctx BlockNode, n Node) Node { + // If initStaticBlocks doesn't happen here, + // it means Preprocess on blocks might fail. + // it works for now because preprocess also does pushInitBlock, + // but it's kinda weird. + // maybe consider moving initStaticBlocks here and ensure idempotency of it. + n = preprocess1(store, ctx, n) + // XXX check node lines and locations + checkNodeLinesLocations("XXXpkgPath", "XXXfileName", n) + // XXX what about the fact that preprocess1 sets the PREPROCESSED attr on all nodes? + // XXX do any of the following need the attr, or similar attrs? + // XXX well the following may be isn't idempotent, + // XXX so it is currently strange. + if bn, ok := n.(BlockNode); ok { + findGotoLoopDefines(ctx, bn) + findLoopUses1(ctx, bn) + findLoopUses2(ctx, bn) + } + return n +} + +func preprocess1(store Store, ctx BlockNode, n Node) Node { // Increment preprocessing counter while preprocessing. preprocessing.Add(1) defer preprocessing.Add(-1) @@ -403,7 +443,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if fn, ok := n.(*FileNode); ok { pkgPath := ctx.(*PackageNode).PkgPath fileName := string(fn.Name) - SetNodeLocations(pkgPath, fileName, fn) + setNodeLines(fn) + setNodeLocations(pkgPath, fileName, fn) } // create stack of BlockNodes. @@ -419,32 +460,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return n, TRANS_SKIP } - defer func() { - if r := recover(); r != nil { - // before re-throwing the error, append location information to message. - loc := last.GetLocation() - if nline := n.GetLine(); nline > 0 { - loc.Line = nline - loc.Column = n.GetColumn() - } - - var err error - rerr, ok := r.(error) - if ok { - // NOTE: gotuna/gorilla expects error exceptions. - err = errors.Wrap(rerr, loc.String()) - } else { - // NOTE: gotuna/gorilla expects error exceptions. - err = fmt.Errorf("%s: %v", loc.String(), r) - } - - // Re-throw the error after wrapping it with the preprocessing stack information. - panic(&PreprocessError{ - err: err, - stack: stack, - }) - } - }() + defer doRecover(stack, n) if debug { debug.Printf("Preprocess %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } @@ -540,7 +556,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *IfCaseStmt: - pushInitRealBlockAndCopy(n, &last, &stack) + pushInitBlockAndCopy(n, &last, &stack) // parent if statement. ifs := ns[len(ns)-1].(*IfStmt) // anything declared in ifs are copied. @@ -624,7 +640,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // create a hidden var with leading dot. // NOTE: document somewhere. - rn := fmt.Sprintf(".res_%d", i) + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) last.Define(Name(rn), anyValue(rf.Type)) } } @@ -656,7 +672,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *SwitchClauseStmt: - pushInitRealBlockAndCopy(n, &last, &stack) + pushInitBlockAndCopy(n, &last, &stack) // parent switch statement. ss := ns[len(ns)-1].(*SwitchStmt) // anything declared in ss are copied, @@ -750,7 +766,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(rf.Name, anyValue(rf.Type)) } else { // create a hidden var with leading dot. - rn := fmt.Sprintf(".res_%d", i) + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) last.Define(Name(rn), anyValue(rf.Type)) } } @@ -869,15 +885,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // in evalStaticType(store,). n.SetAttribute(ATTR_PREPROCESSED, true) - // -There is still work to be done while leaving, but - // once the logic of that is done, we will have to - // perform additionally deferred logic that is best - // handled with orthogonal switch conditions. - // -For example, while leaving nodes w/ - // TRANS_COMPOSITE_TYPE, (regardless of whether name or - // literal), any elided type names are inserted. (This - // works because the transcriber leaves the composite - // type before entering the kv elements.) + // Defer pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + // While leaving nodes w/ TRANS_COMPOSITE_TYPE, + // (regardless of whether name or literal), any elided + // type names are inserted. (This works because the + // transcriber leaves the composite type before + // entering the kv elements.) defer func() { switch ftype { // TRANS_LEAVE (deferred)--------- @@ -963,6 +987,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if ftype == TRANS_ASSIGN_LHS { as := ns[len(ns)-1].(*AssignStmt) fillNameExprPath(last, n, as.Op == DEFINE) + return n, TRANS_CONTINUE + } else if ftype == TRANS_VAR_NAME { + fillNameExprPath(last, n, true) + return n, TRANS_CONTINUE } else { fillNameExprPath(last, n, false) } @@ -1389,7 +1417,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert to byteslice. args1 := n.Args[1] if evalStaticTypeOf(store, last, args1).Kind() == StringKind { - bsx := constType(nil, gByteSliceType) + bsx := constType(n, gByteSliceType) args1 = Call(bsx, args1) args1 = Preprocess(nil, last, args1).(Expr) n.Args[1] = args1 @@ -1424,7 +1452,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert to byteslice. args1 := n.Args[1] if evalStaticTypeOf(store, last, args1).Kind() == StringKind { - bsx := constType(nil, gByteSliceType) + bsx := constType(n, gByteSliceType) args1 = Call(bsx, args1) args1 = Preprocess(nil, last, args1).(Expr) n.Args[1] = args1 @@ -2152,6 +2180,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } + // TRANS_LEAVE ----------------------- case *IncDecStmt: xt := evalStaticTypeOf(store, last, n.X) n.AssertCompatible(xt) @@ -2479,13 +2508,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // end type switch statement // END TRANS_LEAVE ----------------------- - - // finalization (during leave). - if _, ok := n.(BlockNode); ok { - // Pop block. - stack = stack[:len(stack)-1] - last = stack[len(stack)-1] - } return n, TRANS_CONTINUE } @@ -2496,6 +2518,458 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return nn } +// Identifies NameExprTypeHeapDefines. +// Also finds GotoLoopStmts, XXX but probably remove, not needed. +func findGotoLoopDefines(ctx BlockNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = ctx + stack = append(stack, last) + + // iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("findGotoLoopDefines %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_ENTER: + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_LEAVE: + + // Defer pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + switch n := n.(type) { + case *ForStmt, *RangeStmt: + Transcribe(n, + func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + switch stage { + case TRANS_ENTER: + switch n := n.(type) { + case *FuncLitExpr: + // inner funcs. + return n, TRANS_SKIP + case *FuncDecl: + panic("unexpected inner func decl") + case *NameExpr: + if n.Type == NameExprTypeDefine { + n.Type = NameExprTypeHeapDefine + } + } + } + return n, TRANS_CONTINUE + }) + case *BranchStmt: + switch n.Op { + case GOTO: + bn, _, _ := findGotoLabel(last, n.Label) + // already done in Preprocess: + // n.Depth = depth + // n.BodyIndex = index + + // NOTE: we must not use line numbers + // for logic, as line numbers are not + // guaranteed (see checkNodeLinesLocations). + // Instead we rely on the transcribe order + // and keep track of whether we've seen + // the label and goto stmts respectively. + // + // DOES NOT WORK: + // gotoLine := n.GetLine() + // if labelLine >= gotoLine { + // return n, TRANS_SKIP + // } + var ( + label = n.Label + labelReached bool + origGoto = n + ) + + // Recurse and mark stmts as ATTR_GOTOLOOP_STMT. + // NOTE: ATTR_GOTOLOOP_STMT is not used. + Transcribe(bn, + func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + switch stage { + case TRANS_ENTER: + // Check to see if label reached. + if _, ok := n.(Stmt); ok { + // XXX HasLabel + if n.GetLabel() == label { + labelReached = true + } + // If goto < label, + // then not a goto loop. + if n == origGoto && !labelReached { + return n, TRANS_EXIT + } + } + + // If label not reached, continue. + if !labelReached { + return n, TRANS_CONTINUE + } + + // NOTE: called redundantly + // for many goto stmts, + // idempotenct updates only. + switch n := n.(type) { + // Skip the body of these: + case *FuncLitExpr: + if len(ns) > 0 { + // inner funcs. + return n, TRANS_SKIP + } + return n, TRANS_CONTINUE + case *FuncDecl: + if len(ns) > 0 { + panic("unexpected inner func decl") + } + return n, TRANS_CONTINUE + // Otherwise mark stmt as gotoloop. + case Stmt: + // we're done if we + // re-encounter origGotoStmtm. + if n == origGoto { + n.SetAttribute( + ATTR_GOTOLOOP_STMT, + true) + return n, TRANS_EXIT // done + } + // otherwise set attribute. + n.SetAttribute( + ATTR_GOTOLOOP_STMT, + true) + return n, TRANS_CONTINUE + // Special case, maybe convert + // NameExprTypeDefine to + // NameExprTypeHeapDefine. + case *NameExpr: + if n.Type == NameExprTypeDefine { + n.Type = NameExprTypeHeapDefine + } + } + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) + } + } + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + +// Find uses of loop names; those names that are defined as loop defines; +// defines within loops that are used as reference or captured in a closure +// later. Also happens to adjust the type (but not paths) of such usage. +// If there is no usage of the &name or as closure capture, a +// NameExprTypeHeapDefine gets demoted to NameExprTypeDefine in demoteHeapDefines(). +func findLoopUses1(ctx BlockNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = ctx + stack = append(stack, last) + + // Iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("findLoopUses1 %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + + // ---------------------------------------- + case TRANS_ENTER: + switch n := n.(type) { + case *NameExpr: + // Ignore non-block type paths + if n.Path.Type != VPBlock { + return n, TRANS_CONTINUE + } + switch n.Type { + case NameExprTypeNormal: + // Find the block where name is defined + dbn := last.GetBlockNodeForPath(nil, n.Path) + // if the name is loop defined, + lds, _ := dbn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + if slices.Contains(lds, n.Name) { + fle, depth, found := findFirstClosure(stack, dbn) + if found { + // If across a closure, + // mark name as loop used. + addAttrHeapUse(dbn, n.Name) + // The path must stay same for now, + // used later in findLoopUses2. + idx := addHeapCapture(dbn, fle, n.Name) + // adjust NameExpr type. + n.Type = NameExprTypeHeapUse + n.Path.Depth = uint8(depth) + n.Path.Index = idx + } else { + if ftype == TRANS_REF_X { + // if used as a reference, + // mark name as loop used. + addAttrHeapUse(dbn, n.Name) + // Also adjust NameExpr type. + // We could do this later too. + n.Type = NameExprTypeHeapUse + } + } + } else { + // if the name is not loop defined, + // do nothing. + } + case NameExprTypeDefine: + // nothing to do. + case NameExprTypeHeapDefine: + // Set name in attribute, so later matches + // on NameExpr can know that this was loop defined + // on this block. + setAttrHeapDefine(last, n.Name) + case NameExprTypeHeapUse, NameExprTypeHeapClosure: + panic("unexpected node type") + } + } + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_LEAVE: + // Pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + +func assertNotHasName(names []Name, name Name) { + if slices.Contains(names, name) { + panic(fmt.Sprintf("name: %s already contained in names: %v", name, names)) + } +} + +func setAttrHeapDefine(bn BlockNode, name Name) { + bnLDs, _ := bn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + assertNotHasName(bnLDs, name) + bnLDs = append(bnLDs, name) + bn.SetAttribute(ATTR_LOOP_DEFINES, bnLDs) +} + +func addAttrHeapUse(bn BlockNode, name Name) { + bnLUs, _ := bn.GetAttribute(ATTR_LOOP_USES).([]Name) + if slices.Contains(bnLUs, name) { + return + } else { + bnLUs = append(bnLUs, name) + bn.SetAttribute(ATTR_LOOP_USES, bnLUs) + return + } +} + +// adds ~name to fle static block and to heap captures atomically. +func addHeapCapture(dbn BlockNode, fle *FuncLitExpr, name Name) (idx uint16) { + for _, ne := range fle.HeapCaptures { + if ne.Name == name { + // assert ~name also already defined. + var ok bool + idx, ok = fle.GetLocalIndex("~" + name) + if !ok { + panic("~name not added to fle atomically") + } + return // already exists + } + } + + // define ~name to fle. + _, ok := fle.GetLocalIndex("~" + name) + if ok { + panic("~name already defined in fle") + } + + tv := dbn.GetValueRef(nil, name, true) + fle.Define("~"+name, tv.Copy(nil)) + + // add name to fle.HeapCaptures. + vp := fle.GetPathForName(nil, name) + vp.Depth -= 1 // minus 1 for fle itself. + ne := NameExpr{ + Path: vp, + Name: name, + Type: NameExprTypeHeapClosure, + } + fle.HeapCaptures = append(fle.HeapCaptures, ne) + + // find index after define + for i, n := range fle.GetBlockNames() { + if n == "~"+name { + idx = uint16(i) + return + } + } + + panic("should not happen, idx not found") +} + +// finds the first FuncLitExpr in the stack at or after stop. +// returns the depth of first closure, 1 if stop itself is a closure, +// or 0 if not found. +func findFirstClosure(stack []BlockNode, stop BlockNode) (fle *FuncLitExpr, depth int, found bool) { + redundant := 0 // count faux block + for i := len(stack) - 1; i >= 0; i-- { + stbn := stack[i] + switch stbn := stbn.(type) { + case *FuncLitExpr: + if stbn == stop { // if fle is stopBn, does not count, use last fle + return + } + fle = stbn + depth = len(stack) - 1 - redundant - i + 1 // +1 since 1 is lowest. + found = true + // even if found, continue iteration in case + // an earlier *FuncLitExpr is found. + case *IfCaseStmt, *SwitchClauseStmt: + if stbn == stop { + return + } + redundant++ + default: + if stbn == stop { + return + } + } + } + panic("stop not found in stack") +} + +// Convert non-loop uses of loop names to NameExprTypeHeapUse. +// Also, NameExprTypeHeapDefine gets demoted to NameExprTypeDefine if no actual +// usage was found that warrants a NameExprTypeHeapDefine. +func findLoopUses2(ctx BlockNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = ctx + stack = append(stack, last) + + // Iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("findLoopUses2 %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + + // ---------------------------------------- + case TRANS_ENTER: + switch n := n.(type) { + case *NameExpr: + // Ignore non-block type paths + if n.Path.Type != VPBlock { + return n, TRANS_CONTINUE + } + switch n.Type { + case NameExprTypeNormal: + // Find the block where name is defined + dbn := last.GetBlockNodeForPath(nil, n.Path) + // if the name is loop defined, + lds, _ := dbn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + if slices.Contains(lds, n.Name) { + // if the name is actually loop used, + lus, _ := dbn.GetAttribute(ATTR_LOOP_USES).([]Name) + if slices.Contains(lus, n.Name) { + // change type finally to HeapUse. + n.Type = NameExprTypeHeapUse + } else { + // else, will be demoted in later clause. + } + } + case NameExprTypeHeapDefine: + // Find the block where name is defined + dbn := last.GetBlockNodeForPath(nil, n.Path) + // if the name is loop defined + lds, _ := dbn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + if slices.Contains(lds, n.Name) { + // if the name is actually loop used + lus, _ := dbn.GetAttribute(ATTR_LOOP_USES).([]Name) + if !slices.Contains(lus, n.Name) { + // demote type finally to Define. + n.Type = NameExprTypeDefine + } + } + } + } + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_LEAVE: + + // Defer pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + switch n := n.(type) { + case BlockNode: + lds, _ := n.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + lus, _ := n.GetAttribute(ATTR_LOOP_USES).([]Name) + if len(lds) < len(lus) { + panic("defines should be a superset of used-defines") + } + // no need anymore + n.DelAttribute(ATTR_LOOP_USES) + n.DelAttribute(ATTR_LOOP_DEFINES) + } + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + func isSwitchLabel(ns []Node, label Name) bool { for { swch := lastSwitch(ns) @@ -2514,37 +2988,38 @@ func isSwitchLabel(ns []Node, label Name) bool { } // Idempotent. +// Also makes sure the stack doesn't reach MaxUint8 in length. func pushInitBlock(bn BlockNode, last *BlockNode, stack *[]BlockNode) { if !bn.IsInitialized() { - bn.InitStaticBlock(bn, *last) + switch bn.(type) { + case *IfCaseStmt, *SwitchClauseStmt: + // skip faux block + bn.InitStaticBlock(bn, (*last).GetParentNode(nil)) + default: + bn.InitStaticBlock(bn, *last) + } } if bn.GetStaticBlock().Source != bn { panic("expected the source of a block node to be itself") } *last = bn *stack = append(*stack, bn) -} - -// like pushInitBlock(), but when the last block is a faux block, -// namely after SwitchStmt and IfStmt. -// Idempotent. -func pushInitRealBlock(bn BlockNode, last *BlockNode, stack *[]BlockNode) { - if !bn.IsInitialized() { - bn.InitStaticBlock(bn, (*last).GetParentNode(nil)) - } - if bn.GetStaticBlock().Source != bn { - panic("expected the source of a block node to be itself") + if len(*stack) >= math.MaxUint8 { + panic("block node depth reached maximum MaxUint8") } - *last = bn - *stack = append(*stack, bn) } // like pushInitBlock(), but when the last block is a faux block, // namely after SwitchStmt and IfStmt. // Not idempotent, as it calls bn.Define with reference to last's TV value slot. -func pushInitRealBlockAndCopy(bn BlockNode, last *BlockNode, stack *[]BlockNode) { +func pushInitBlockAndCopy(bn BlockNode, last *BlockNode, stack *[]BlockNode) { + if _, ok := bn.(*IfCaseStmt); !ok { + if _, ok := bn.(*SwitchClauseStmt); !ok { + panic("should not happen") + } + } orig := *last - pushInitRealBlock(bn, last, stack) + pushInitBlock(bn, last, stack) copyFromFauxBlock(bn, orig) } @@ -2750,6 +3225,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { Source: x, TypedValue: cv, } + cx.SetLine(x.GetLine()) cx.SetAttribute(ATTR_PREPROCESSED, true) setConstAttrs(cx) return cx @@ -2758,6 +3234,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { func constType(source Expr, t Type) *constTypeExpr { cx := &constTypeExpr{Source: source} cx.Type = t + cx.SetLine(source.GetLine()) cx.SetAttribute(ATTR_PREPROCESSED, true) return cx } @@ -3060,7 +3537,7 @@ func convertType(store Store, last BlockNode, x *Expr, t Type) { // convert x to destination type t func doConvertType(store Store, last BlockNode, x *Expr, t Type) { - cx := Expr(Call(constType(nil, t), *x)) + cx := Expr(Call(constType(*x, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx } @@ -3296,7 +3773,7 @@ func findUndefined2(store Store, last BlockNode, x Expr, t Type) (un Name) { panic("cannot elide unknown composite type") } ct = t - cx.Type = constType(nil, t) + cx.Type = constType(cx, t) } else { un = findUndefined(store, last, cx.Type) if un != "" { @@ -3880,10 +4357,6 @@ func fillNameExprPath(last BlockNode, nx *NameExpr, isDefineLHS bool) { } // If not DEFINE_LHS, yet is statically undefined, set path from parent. - - // NOTE: ValueDecl names don't need this distinction, as - // the transcriber doesn't enter any of the ValueDecl.NameExprs nodes, - // so this function never gets called for them. if !isDefineLHS { if last.GetStaticTypeOf(nil, nx.Name) == nil { // NOTE: We cannot simply call last.GetPathForName() as below here, @@ -4215,13 +4688,38 @@ func isLocallyDefined(bn BlockNode, n Name) bool { return true } +// r := 0 +// r, ok := 1, true +func isLocallyDefined2(bn BlockNode, n Name) bool { + _, isLocal := bn.GetLocalIndex(n) + return isLocal +} + // ---------------------------------------- -// SetNodeLocations +// setNodeLines & setNodeLocations -// Iterate over all block nodes recursively and sets location information -// based on sparse expectations, and ensures uniqueness of BlockNode.Locations. +func setNodeLines(n Node) { + lastLine := 0 + Transcribe(n, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + if stage != TRANS_ENTER { + return n, TRANS_CONTINUE + } + line := n.GetLine() + if line == lastLine { + } else if line == 0 { + line = lastLine + } else { + lastLine = line + } + n.SetLine(line) + return n, TRANS_CONTINUE + }) +} + +// Iterate over all nodes recursively and sets location information +// based on sparse expectations on block nodes, and ensures uniqueness of BlockNode.Locations. // Ensures uniqueness of BlockNode.Locations. -func SetNodeLocations(pkgPath string, fileName string, n Node) { +func setNodeLocations(pkgPath string, fileName string, n Node) { if n.GetAttribute(ATTR_LOCATIONED) == true { return // locations already set (typically n is a filenode). } @@ -4246,6 +4744,13 @@ func SetNodeLocations(pkgPath string, fileName string, n Node) { }) } +// XXX check node lines, uniqueness of locations, +// and also check location pkgpath and filename. +// Even after this is implemented, locations should not be used for logic. +func checkNodeLinesLocations(pkgPath string, fileName string, n Node) { + // TODO: XXX +} + // ---------------------------------------- // SaveBlockNodes diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 3710524130a7..5913f13a0f7d 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -845,6 +845,9 @@ func getChildObjects(val Value, more []Value) []Value { if bv, ok := cv.Closure.(*Block); ok { more = getSelfOrChildObjects(bv, more) } + for _, c := range cv.Captures { + more = getSelfOrChildObjects(c.V, more) + } return more case *BoundMethodValue: more = getChildObjects(cv.Func, more) // *FuncValue not object @@ -1142,6 +1145,7 @@ func copyValueWithRefs(val Value) Value { Source: source, Name: cv.Name, Closure: closure, + Captures: cv.Captures, FileName: cv.FileName, PkgPath: cv.PkgPath, NativePkg: cv.NativePkg, diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index 0e6d89a7bf38..9913c434282b 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -47,7 +47,7 @@ type Store interface { GetTypeSafe(tid TypeID) Type SetCacheType(Type) SetType(Type) - GetBlockNode(Location) BlockNode + GetBlockNode(Location) BlockNode // to get a PackageNode, use PackageNodeLocation(). GetBlockNodeSafe(Location) BlockNode SetBlockNode(BlockNode) // UNSTABLE diff --git a/gnovm/pkg/gnolang/transcribe.go b/gnovm/pkg/gnolang/transcribe.go index 28e97ff2b5bf..dab539a8707c 100644 --- a/gnovm/pkg/gnolang/transcribe.go +++ b/gnovm/pkg/gnolang/transcribe.go @@ -47,6 +47,7 @@ const ( TRANS_COMPOSITE_KEY TRANS_COMPOSITE_VALUE TRANS_FUNCLIT_TYPE + TRANS_FUNCLIT_HEAP_CAPTURE TRANS_FUNCLIT_BODY TRANS_FIELDTYPE_TYPE TRANS_FIELDTYPE_TAG @@ -100,6 +101,7 @@ const ( TRANS_IMPORT_PATH TRANS_CONST_TYPE TRANS_CONST_VALUE + TRANS_VAR_NAME // XXX stringer TRANS_VAR_TYPE TRANS_VAR_VALUE TRANS_TYPE_TYPE @@ -112,6 +114,7 @@ const ( // ENTER,CHILDS1,[BLOCK,CHILDS2]?,LEAVE sequence for that node, // i.e. skipping (the rest of) it; // - TRANS_BREAK to break out of looping in CHILDS1 or CHILDS2, +// but still perform TRANS_LEAVE. // - TRANS_EXIT to stop traversing altogether. // // Do not mutate ns. @@ -264,6 +267,14 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc if isStopOrSkip(nc, c) { return } + for idx := range cnn.HeapCaptures { + cnn.HeapCaptures[idx] = *(transcribe(t, nns, TRANS_FUNCLIT_HEAP_CAPTURE, idx, &cnn.HeapCaptures[idx], &c).(*NameExpr)) + if isBreak(c) { + break + } else if isStopOrSkip(nc, c) { + return + } + } cnn2, c2 := t(ns, ftype, index, cnn, TRANS_BLOCK) if isStopOrSkip(nc, c2) { nn = cnn2 @@ -692,6 +703,10 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc return } } + // XXX consider RHS, LHS, RHS, LHS, ... order. + for idx := range cnn.NameExprs { + cnn.NameExprs[idx] = *(transcribe(t, nns, TRANS_VAR_NAME, idx, &cnn.NameExprs[idx], &c).(*NameExpr)) + } for idx := range cnn.Values { cnn.Values[idx] = transcribe(t, nns, TRANS_VAR_VALUE, idx, cnn.Values[idx], &c).(Expr) if isBreak(c) { diff --git a/gnovm/pkg/gnolang/transfield_string.go b/gnovm/pkg/gnolang/transfield_string.go index 587ca7a7654a..31afcf2be0d4 100644 --- a/gnovm/pkg/gnolang/transfield_string.go +++ b/gnovm/pkg/gnolang/transfield_string.go @@ -29,68 +29,70 @@ func _() { _ = x[TRANS_COMPOSITE_KEY-18] _ = x[TRANS_COMPOSITE_VALUE-19] _ = x[TRANS_FUNCLIT_TYPE-20] - _ = x[TRANS_FUNCLIT_BODY-21] - _ = x[TRANS_FIELDTYPE_TYPE-22] - _ = x[TRANS_FIELDTYPE_TAG-23] - _ = x[TRANS_ARRAYTYPE_LEN-24] - _ = x[TRANS_ARRAYTYPE_ELT-25] - _ = x[TRANS_SLICETYPE_ELT-26] - _ = x[TRANS_INTERFACETYPE_METHOD-27] - _ = x[TRANS_CHANTYPE_VALUE-28] - _ = x[TRANS_FUNCTYPE_PARAM-29] - _ = x[TRANS_FUNCTYPE_RESULT-30] - _ = x[TRANS_MAPTYPE_KEY-31] - _ = x[TRANS_MAPTYPE_VALUE-32] - _ = x[TRANS_STRUCTTYPE_FIELD-33] - _ = x[TRANS_MAYBENATIVETYPE_TYPE-34] - _ = x[TRANS_ASSIGN_LHS-35] - _ = x[TRANS_ASSIGN_RHS-36] - _ = x[TRANS_BLOCK_BODY-37] - _ = x[TRANS_DECL_BODY-38] - _ = x[TRANS_DEFER_CALL-39] - _ = x[TRANS_EXPR_X-40] - _ = x[TRANS_FOR_INIT-41] - _ = x[TRANS_FOR_COND-42] - _ = x[TRANS_FOR_POST-43] - _ = x[TRANS_FOR_BODY-44] - _ = x[TRANS_GO_CALL-45] - _ = x[TRANS_IF_INIT-46] - _ = x[TRANS_IF_COND-47] - _ = x[TRANS_IF_BODY-48] - _ = x[TRANS_IF_ELSE-49] - _ = x[TRANS_IF_CASE_BODY-50] - _ = x[TRANS_INCDEC_X-51] - _ = x[TRANS_RANGE_X-52] - _ = x[TRANS_RANGE_KEY-53] - _ = x[TRANS_RANGE_VALUE-54] - _ = x[TRANS_RANGE_BODY-55] - _ = x[TRANS_RETURN_RESULT-56] - _ = x[TRANS_PANIC_EXCEPTION-57] - _ = x[TRANS_SELECT_CASE-58] - _ = x[TRANS_SELECTCASE_COMM-59] - _ = x[TRANS_SELECTCASE_BODY-60] - _ = x[TRANS_SEND_CHAN-61] - _ = x[TRANS_SEND_VALUE-62] - _ = x[TRANS_SWITCH_INIT-63] - _ = x[TRANS_SWITCH_X-64] - _ = x[TRANS_SWITCH_CASE-65] - _ = x[TRANS_SWITCHCASE_CASE-66] - _ = x[TRANS_SWITCHCASE_BODY-67] - _ = x[TRANS_FUNC_RECV-68] - _ = x[TRANS_FUNC_TYPE-69] - _ = x[TRANS_FUNC_BODY-70] - _ = x[TRANS_IMPORT_PATH-71] - _ = x[TRANS_CONST_TYPE-72] - _ = x[TRANS_CONST_VALUE-73] - _ = x[TRANS_VAR_TYPE-74] - _ = x[TRANS_VAR_VALUE-75] - _ = x[TRANS_TYPE_TYPE-76] - _ = x[TRANS_FILE_BODY-77] + _ = x[TRANS_FUNCLIT_HEAP_CAPTURE-21] + _ = x[TRANS_FUNCLIT_BODY-22] + _ = x[TRANS_FIELDTYPE_TYPE-23] + _ = x[TRANS_FIELDTYPE_TAG-24] + _ = x[TRANS_ARRAYTYPE_LEN-25] + _ = x[TRANS_ARRAYTYPE_ELT-26] + _ = x[TRANS_SLICETYPE_ELT-27] + _ = x[TRANS_INTERFACETYPE_METHOD-28] + _ = x[TRANS_CHANTYPE_VALUE-29] + _ = x[TRANS_FUNCTYPE_PARAM-30] + _ = x[TRANS_FUNCTYPE_RESULT-31] + _ = x[TRANS_MAPTYPE_KEY-32] + _ = x[TRANS_MAPTYPE_VALUE-33] + _ = x[TRANS_STRUCTTYPE_FIELD-34] + _ = x[TRANS_MAYBENATIVETYPE_TYPE-35] + _ = x[TRANS_ASSIGN_LHS-36] + _ = x[TRANS_ASSIGN_RHS-37] + _ = x[TRANS_BLOCK_BODY-38] + _ = x[TRANS_DECL_BODY-39] + _ = x[TRANS_DEFER_CALL-40] + _ = x[TRANS_EXPR_X-41] + _ = x[TRANS_FOR_INIT-42] + _ = x[TRANS_FOR_COND-43] + _ = x[TRANS_FOR_POST-44] + _ = x[TRANS_FOR_BODY-45] + _ = x[TRANS_GO_CALL-46] + _ = x[TRANS_IF_INIT-47] + _ = x[TRANS_IF_COND-48] + _ = x[TRANS_IF_BODY-49] + _ = x[TRANS_IF_ELSE-50] + _ = x[TRANS_IF_CASE_BODY-51] + _ = x[TRANS_INCDEC_X-52] + _ = x[TRANS_RANGE_X-53] + _ = x[TRANS_RANGE_KEY-54] + _ = x[TRANS_RANGE_VALUE-55] + _ = x[TRANS_RANGE_BODY-56] + _ = x[TRANS_RETURN_RESULT-57] + _ = x[TRANS_PANIC_EXCEPTION-58] + _ = x[TRANS_SELECT_CASE-59] + _ = x[TRANS_SELECTCASE_COMM-60] + _ = x[TRANS_SELECTCASE_BODY-61] + _ = x[TRANS_SEND_CHAN-62] + _ = x[TRANS_SEND_VALUE-63] + _ = x[TRANS_SWITCH_INIT-64] + _ = x[TRANS_SWITCH_X-65] + _ = x[TRANS_SWITCH_CASE-66] + _ = x[TRANS_SWITCHCASE_CASE-67] + _ = x[TRANS_SWITCHCASE_BODY-68] + _ = x[TRANS_FUNC_RECV-69] + _ = x[TRANS_FUNC_TYPE-70] + _ = x[TRANS_FUNC_BODY-71] + _ = x[TRANS_IMPORT_PATH-72] + _ = x[TRANS_CONST_TYPE-73] + _ = x[TRANS_CONST_VALUE-74] + _ = x[TRANS_VAR_NAME-75] + _ = x[TRANS_VAR_TYPE-76] + _ = x[TRANS_VAR_VALUE-77] + _ = x[TRANS_TYPE_TYPE-78] + _ = x[TRANS_FILE_BODY-79] } -const _TransField_name = "TRANS_ROOTTRANS_BINARY_LEFTTRANS_BINARY_RIGHTTRANS_CALL_FUNCTRANS_CALL_ARGTRANS_INDEX_XTRANS_INDEX_INDEXTRANS_SELECTOR_XTRANS_SLICE_XTRANS_SLICE_LOWTRANS_SLICE_HIGHTRANS_SLICE_MAXTRANS_STAR_XTRANS_REF_XTRANS_TYPEASSERT_XTRANS_TYPEASSERT_TYPETRANS_UNARY_XTRANS_COMPOSITE_TYPETRANS_COMPOSITE_KEYTRANS_COMPOSITE_VALUETRANS_FUNCLIT_TYPETRANS_FUNCLIT_BODYTRANS_FIELDTYPE_TYPETRANS_FIELDTYPE_TAGTRANS_ARRAYTYPE_LENTRANS_ARRAYTYPE_ELTTRANS_SLICETYPE_ELTTRANS_INTERFACETYPE_METHODTRANS_CHANTYPE_VALUETRANS_FUNCTYPE_PARAMTRANS_FUNCTYPE_RESULTTRANS_MAPTYPE_KEYTRANS_MAPTYPE_VALUETRANS_STRUCTTYPE_FIELDTRANS_MAYBENATIVETYPE_TYPETRANS_ASSIGN_LHSTRANS_ASSIGN_RHSTRANS_BLOCK_BODYTRANS_DECL_BODYTRANS_DEFER_CALLTRANS_EXPR_XTRANS_FOR_INITTRANS_FOR_CONDTRANS_FOR_POSTTRANS_FOR_BODYTRANS_GO_CALLTRANS_IF_INITTRANS_IF_CONDTRANS_IF_BODYTRANS_IF_ELSETRANS_IF_CASE_BODYTRANS_INCDEC_XTRANS_RANGE_XTRANS_RANGE_KEYTRANS_RANGE_VALUETRANS_RANGE_BODYTRANS_RETURN_RESULTTRANS_PANIC_EXCEPTIONTRANS_SELECT_CASETRANS_SELECTCASE_COMMTRANS_SELECTCASE_BODYTRANS_SEND_CHANTRANS_SEND_VALUETRANS_SWITCH_INITTRANS_SWITCH_XTRANS_SWITCH_CASETRANS_SWITCHCASE_CASETRANS_SWITCHCASE_BODYTRANS_FUNC_RECVTRANS_FUNC_TYPETRANS_FUNC_BODYTRANS_IMPORT_PATHTRANS_CONST_TYPETRANS_CONST_VALUETRANS_VAR_TYPETRANS_VAR_VALUETRANS_TYPE_TYPETRANS_FILE_BODY" +const _TransField_name = "TRANS_ROOTTRANS_BINARY_LEFTTRANS_BINARY_RIGHTTRANS_CALL_FUNCTRANS_CALL_ARGTRANS_INDEX_XTRANS_INDEX_INDEXTRANS_SELECTOR_XTRANS_SLICE_XTRANS_SLICE_LOWTRANS_SLICE_HIGHTRANS_SLICE_MAXTRANS_STAR_XTRANS_REF_XTRANS_TYPEASSERT_XTRANS_TYPEASSERT_TYPETRANS_UNARY_XTRANS_COMPOSITE_TYPETRANS_COMPOSITE_KEYTRANS_COMPOSITE_VALUETRANS_FUNCLIT_TYPETRANS_FUNCLIT_HEAP_CAPTURETRANS_FUNCLIT_BODYTRANS_FIELDTYPE_TYPETRANS_FIELDTYPE_TAGTRANS_ARRAYTYPE_LENTRANS_ARRAYTYPE_ELTTRANS_SLICETYPE_ELTTRANS_INTERFACETYPE_METHODTRANS_CHANTYPE_VALUETRANS_FUNCTYPE_PARAMTRANS_FUNCTYPE_RESULTTRANS_MAPTYPE_KEYTRANS_MAPTYPE_VALUETRANS_STRUCTTYPE_FIELDTRANS_MAYBENATIVETYPE_TYPETRANS_ASSIGN_LHSTRANS_ASSIGN_RHSTRANS_BLOCK_BODYTRANS_DECL_BODYTRANS_DEFER_CALLTRANS_EXPR_XTRANS_FOR_INITTRANS_FOR_CONDTRANS_FOR_POSTTRANS_FOR_BODYTRANS_GO_CALLTRANS_IF_INITTRANS_IF_CONDTRANS_IF_BODYTRANS_IF_ELSETRANS_IF_CASE_BODYTRANS_INCDEC_XTRANS_RANGE_XTRANS_RANGE_KEYTRANS_RANGE_VALUETRANS_RANGE_BODYTRANS_RETURN_RESULTTRANS_PANIC_EXCEPTIONTRANS_SELECT_CASETRANS_SELECTCASE_COMMTRANS_SELECTCASE_BODYTRANS_SEND_CHANTRANS_SEND_VALUETRANS_SWITCH_INITTRANS_SWITCH_XTRANS_SWITCH_CASETRANS_SWITCHCASE_CASETRANS_SWITCHCASE_BODYTRANS_FUNC_RECVTRANS_FUNC_TYPETRANS_FUNC_BODYTRANS_IMPORT_PATHTRANS_CONST_TYPETRANS_CONST_VALUETRANS_VAR_NAMETRANS_VAR_TYPETRANS_VAR_VALUETRANS_TYPE_TYPETRANS_FILE_BODY" -var _TransField_index = [...]uint16{0, 10, 27, 45, 60, 74, 87, 104, 120, 133, 148, 164, 179, 191, 202, 220, 241, 254, 274, 293, 314, 332, 350, 370, 389, 408, 427, 446, 472, 492, 512, 533, 550, 569, 591, 617, 633, 649, 665, 680, 696, 708, 722, 736, 750, 764, 777, 790, 803, 816, 829, 847, 861, 874, 889, 906, 922, 941, 962, 979, 1000, 1021, 1036, 1052, 1069, 1083, 1100, 1121, 1142, 1157, 1172, 1187, 1204, 1220, 1237, 1251, 1266, 1281, 1296} +var _TransField_index = [...]uint16{0, 10, 27, 45, 60, 74, 87, 104, 120, 133, 148, 164, 179, 191, 202, 220, 241, 254, 274, 293, 314, 332, 358, 376, 396, 415, 434, 453, 472, 498, 518, 538, 559, 576, 595, 617, 643, 659, 675, 691, 706, 722, 734, 748, 762, 776, 790, 803, 816, 829, 842, 855, 873, 887, 900, 915, 932, 948, 967, 988, 1005, 1026, 1047, 1062, 1078, 1095, 1109, 1126, 1147, 1168, 1183, 1198, 1213, 1230, 1246, 1263, 1277, 1291, 1306, 1321, 1336} func (i TransField) String() string { if i >= TransField(len(_TransField_index)-1) { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 2dec832fd0db..f86c44e79214 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -855,8 +855,8 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { if x.Op == ASSIGN { // check assignable for i, lx := range x.Lhs { + assertValidAssignLhs(store, last, lx) if !isBlankIdentifier(lx) { - assertValidAssignLhs(store, last, lx) lxt := evalStaticTypeOf(store, last, lx) assertAssignableTo(cft.Results[i].Type, lxt, false) } @@ -868,15 +868,16 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } if x.Op == ASSIGN { - // check assignable to first value + // check first value + assertValidAssignLhs(store, last, x.Lhs[0]) if !isBlankIdentifier(x.Lhs[0]) { // see composite3.gno - assertValidAssignLhs(store, last, x.Lhs[0]) dt := evalStaticTypeOf(store, last, x.Lhs[0]) ift := evalStaticTypeOf(store, last, cx) assertAssignableTo(ift, dt, false) } + // check second value + assertValidAssignLhs(store, last, x.Lhs[1]) if !isBlankIdentifier(x.Lhs[1]) { // see composite3.gno - assertValidAssignLhs(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -889,8 +890,8 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } if x.Op == ASSIGN { + assertValidAssignLhs(store, last, x.Lhs[0]) if !isBlankIdentifier(x.Lhs[0]) { - assertValidAssignLhs(store, last, x.Lhs[0]) lt := evalStaticTypeOf(store, last, x.Lhs[0]) if _, ok := cx.X.(*NameExpr); ok { rt := evalStaticTypeOf(store, last, cx.X) @@ -906,8 +907,9 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } + + assertValidAssignLhs(store, last, x.Lhs[1]) if !isBlankIdentifier(x.Lhs[1]) { - assertValidAssignLhs(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt != nil && dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -973,7 +975,17 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { func assertValidAssignLhs(store Store, last BlockNode, lx Expr) { shouldPanic := true switch clx := lx.(type) { - case *NameExpr, *StarExpr, *SelectorExpr: + case *NameExpr: + if clx.Name == blankIdentifier { + shouldPanic = false + } else if clx.Path.Type == VPUverse { + panic(fmt.Sprintf("cannot assign to uverse %v", clx.Name)) + } else if last.GetIsConst(store, clx.Name) { + panic(fmt.Sprintf("cannot assign to const %v", clx.Name)) + } else { + shouldPanic = false + } + case *StarExpr, *SelectorExpr: shouldPanic = false case *IndexExpr: xt := evalStaticTypeOf(store, last, clx.X) @@ -1017,7 +1029,7 @@ func isComparison(op Word) bool { // it returns true, indicating a swap is needed. func shouldSwapOnSpecificity(t1, t2 Type) bool { // check nil - if t1 == nil { // see test file 0f46 + if t1 == nil { return false // also with both nil } else if t2 == nil { return true @@ -1056,7 +1068,7 @@ func shouldSwapOnSpecificity(t1, t2 Type) bool { func isBlankIdentifier(x Expr) bool { if nx, ok := x.(*NameExpr); ok { - return nx.Name == "_" + return nx.Name == blankIdentifier } return false } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index b43f623ea99b..eedb71ffa73b 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -69,6 +69,7 @@ func (*PackageType) assertType() {} func (*ChanType) assertType() {} func (*NativeType) assertType() {} func (blockType) assertType() {} +func (heapItemType) assertType() {} func (*tupleType) assertType() {} func (RefType) assertType() {} func (MaybeNativeType) assertType() {} @@ -1964,6 +1965,35 @@ func (bt blockType) IsNamed() bool { panic("blockType has no property called named") } +// ---------------------------------------- +// heapItemType + +type heapItemType struct{} // no data + +func (bt heapItemType) Kind() Kind { + return HeapItemKind +} + +func (bt heapItemType) TypeID() TypeID { + return typeid("heapitem") +} + +func (bt heapItemType) String() string { + return "heapitem" +} + +func (bt heapItemType) Elem() Type { + panic("heapItemType has no elem type") +} + +func (bt heapItemType) GetPkgPath() string { + panic("heapItemType has no package path") +} + +func (bt heapItemType) IsNamed() bool { + panic("heapItemType has no property called named") +} + // ---------------------------------------- // tupleType @@ -2118,9 +2148,10 @@ const ( MapKind TypeKind // not in go. // UnsafePointerKind - BlockKind // not in go. - TupleKind // not in go. - RefTypeKind // not in go. + BlockKind // not in go. + HeapItemKind // not in go. + TupleKind // not in go. + RefTypeKind // not in go. ) // This is generally slower than switching on baseOf(t). @@ -2193,6 +2224,8 @@ func KindOf(t Type) Kind { return t.Kind() case blockType: return BlockKind + case heapItemType: + return HeapItemKind case *tupleType: return TupleKind case RefType: diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 2761d3f574b8..68c2967811f2 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -534,12 +534,13 @@ func (sv *StructValue) Copy(alloc *Allocator) *StructValue { // makes construction TypedValue{T:*FuncType{},V:*FuncValue{}} // faster. type FuncValue struct { - Type Type // includes unbound receiver(s) - IsMethod bool // is an (unbound) method - Source BlockNode // for block mem allocation - Name Name // name of function/method - Closure Value // *Block or RefValue to closure (may be nil for file blocks; lazy) - FileName Name // file name where declared + Type Type // includes unbound receiver(s) + IsMethod bool // is an (unbound) method + Source BlockNode // for block mem allocation + Name Name // name of function/method + Closure Value // *Block or RefValue to closure (may be nil for file blocks; lazy) + Captures []TypedValue `json:",omitempty"` // HeapItemValues captured from closure. + FileName Name // file name where declared PkgPath string NativePkg string // for native bindings through NativeStore NativeName Name // not redundant with Name; this cannot be changed in userspace @@ -1645,10 +1646,10 @@ func (tv *TypedValue) Assign(alloc *Allocator, tv2 TypedValue, cu bool) { // or binary operations. When a pointer is to be // allocated, *Allocator.AllocatePointer() is called separately, // as in OpRef. -func (tv *TypedValue) GetPointerTo(alloc *Allocator, store Store, path ValuePath) PointerValue { +func (tv *TypedValue) GetPointerToFromTV(alloc *Allocator, store Store, path ValuePath) PointerValue { if debug { if tv.IsUndefined() { - panic("GetPointerTo() on undefined value") + panic("GetPointerToFromTV() on undefined value") } } @@ -1867,7 +1868,7 @@ func (tv *TypedValue) GetPointerTo(alloc *Allocator, store Store, path ValuePath } bv := *dtv for i, path := range tr { - ptr := bv.GetPointerTo(alloc, store, path) + ptr := bv.GetPointerToFromTV(alloc, store, path) if i == len(tr)-1 { return ptr // done } @@ -2436,6 +2437,70 @@ func (b *Block) GetPointerTo(store Store, path ValuePath) PointerValue { return b.GetPointerToInt(store, int(path.Index)) } +// Convenience +func (b *Block) GetPointerToMaybeHeapUse(store Store, nx *NameExpr) PointerValue { + switch nx.Type { + case NameExprTypeNormal: + return b.GetPointerTo(store, nx.Path) + case NameExprTypeHeapUse: + return b.GetPointerToHeapUse(store, nx.Path) + case NameExprTypeHeapClosure: + panic("should not happen with type heap closure") + default: + panic("unexpected NameExpr type for GetPointerToMaybeHeapUse") + } +} + +// Convenience +func (b *Block) GetPointerToMaybeHeapDefine(store Store, nx *NameExpr) PointerValue { + switch nx.Type { + case NameExprTypeNormal: + return b.GetPointerTo(store, nx.Path) + case NameExprTypeDefine: + return b.GetPointerTo(store, nx.Path) + case NameExprTypeHeapDefine: + return b.GetPointerToHeapDefine(store, nx.Path) + default: + panic("unexpected NameExpr type for GetPointerToMaybeHeapDefine") + } +} + +// First defines a new HeapItemValue. +// This gets called from NameExprTypeHeapDefine name expressions. +func (b *Block) GetPointerToHeapDefine(store Store, path ValuePath) PointerValue { + ptr := b.GetPointerTo(store, path) + hiv := &HeapItemValue{} + // point to a heapItem + *ptr.TV = TypedValue{ + T: heapItemType{}, + V: hiv, + } + + return PointerValue{ + TV: &hiv.Value, + Base: hiv, + Index: 0, + } +} + +// Assumes a HeapItemValue, and gets inner pointer. +// This gets called from NameExprTypeHeapUse name expressions. +func (b *Block) GetPointerToHeapUse(store Store, path ValuePath) PointerValue { + ptr := b.GetPointerTo(store, path) + if _, ok := ptr.TV.T.(heapItemType); !ok { + panic("should not happen, should be heapItemType") + } + if _, ok := ptr.TV.V.(*HeapItemValue); !ok { + panic("should not happen, should be HeapItemValue") + } + + return PointerValue{ + TV: &ptr.TV.V.(*HeapItemValue).Value, + Base: ptr.TV.V, + Index: 0, + } +} + // Result is used has lhs for any assignments to "_". func (b *Block) GetBlankRef() *TypedValue { return &b.Blank diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 1be2a0516f95..f45beffe6480 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -110,7 +110,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { opt(&f) } - directives, pkgPath, resWanted, errWanted, rops, stacktraceWanted, maxAlloc, send := wantedFromComment(path) + directives, pkgPath, resWanted, errWanted, rops, stacktraceWanted, maxAlloc, send, preWanted := wantedFromComment(path) if pkgPath == "" { pkgPath = "main" } @@ -377,6 +377,28 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { } } } + case "Preprocessed": + // check preprocessed AST. + pn := store.GetBlockNode(gno.PackageNodeLocation(pkgPath)) + pre := pn.(*gno.PackageNode).FileSet.Files[0].String() + if pre != preWanted { + if f.syncWanted { + // write error to file + replaceWantedInPlace(path, "Preprocessed", pre) + } else { + // panic so tests immediately fail (for now). + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(preWanted), + B: difflib.SplitLines(pre), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + } + } case "Stacktrace": if stacktraceWanted != "" { var stacktrace string @@ -388,22 +410,27 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { stacktrace = m.Stacktrace().String() } - if !strings.Contains(stacktrace, stacktraceWanted) { - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(stacktraceWanted), - B: difflib.SplitLines(stacktrace), - FromFile: "Expected", - FromDate: "", - ToFile: "Actual", - ToDate: "", - Context: 1, - }) - panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + if f.syncWanted { + // write stacktrace to file + replaceWantedInPlace(path, "Stacktrace", stacktrace) + } else { + if !strings.Contains(stacktrace, stacktraceWanted) { + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(stacktraceWanted), + B: difflib.SplitLines(stacktrace), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + } } } checkMachineIsEmpty = false default: - checkMachineIsEmpty = false + return nil } } } @@ -421,7 +448,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { return nil } -func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, stacktrace string, maxAlloc int64, send std.Coins) { +func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, stacktrace string, maxAlloc int64, send std.Coins, pre string) { fset := token.NewFileSet() f, err2 := parser.ParseFile(fset, p, nil, parser.ParseComments) if err2 != nil { @@ -463,6 +490,10 @@ func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, rops = strings.TrimPrefix(text, "Realm:\n") rops = strings.TrimSpace(rops) directives = append(directives, "Realm") + } else if strings.HasPrefix(text, "Preprocessed:\n") { + pre = strings.TrimPrefix(text, "Preprocessed:\n") + pre = strings.TrimSpace(pre) + directives = append(directives, "Preprocessed") } else if strings.HasPrefix(text, "Stacktrace:\n") { stacktrace = strings.TrimPrefix(text, "Stacktrace:\n") stacktrace = strings.TrimSpace(stacktrace) diff --git a/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno index 5bdd878c146f..d61170334d71 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno @@ -1,10 +1,6 @@ // PKGPATH: gno.land/r/test package test -import ( - "fmt" -) - type ( word uint nat []word @@ -226,7 +222,7 @@ func main() { // "Location": { // "Column": "1", // "File": "main.gno", -// "Line": "20", +// "Line": "16", // "PkgPath": "gno.land/r/test" // } // }, diff --git a/gnovm/tests/files/heap_alloc_defer.gno b/gnovm/tests/files/heap_alloc_defer.gno new file mode 100644 index 000000000000..788d93266953 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_defer.gno @@ -0,0 +1,37 @@ +package main + +type Foo struct { + num int + f func() +} + +func main() { + s := []Foo{ + { + num: 1, + f: func() { println("hello") }, + }, + { + num: 2, + f: func() { println("hola") }, + }, + } + + // tt is heap defined every iteration, + // different with for loopvar spec. + for _, tt := range s { + f := func() { + println(tt.num) + } + f() + defer func() { + tt.f() + }() + } +} + +// Output: +// 1 +// 2 +// hola +// hola diff --git a/gnovm/tests/files/heap_alloc_defer2.gno b/gnovm/tests/files/heap_alloc_defer2.gno new file mode 100644 index 000000000000..dc865b1a430f --- /dev/null +++ b/gnovm/tests/files/heap_alloc_defer2.gno @@ -0,0 +1,28 @@ +package main + +type rand struct{} + +func (r *rand) Seed() { + println("seed...") +} + +func fromSeed() *rand { + return &rand{} +} + +func genResult(s0 string, x int) (int, bool) { + z := 0 + println(z) + r := fromSeed() + defer func() { r.Seed() }() + + return -1, true +} + +func main() { + genResult("hey", 0) +} + +// Output: +// 0 +// seed... diff --git a/gnovm/tests/files/heap_alloc_forloop1.gno b/gnovm/tests/files/heap_alloc_forloop1.gno new file mode 100644 index 000000000000..c166bf8e167b --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop1.gno @@ -0,0 +1,31 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(i<~VPBlock(1,0)>)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 3 +// s1[1] is: 3 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop1a.gno b/gnovm/tests/files/heap_alloc_forloop1a.gno new file mode 100644 index 000000000000..6d0895902bd4 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop1a.gno @@ -0,0 +1,39 @@ +package main + +import "fmt" + +type Int int + +var s1 []*Int + +func inc2(j *Int) { + *j = *j + 2 // Just as an example, increment j by 2. +} + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := Int(0); i < 10; inc2(&i) { + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; type Int (const-type main.Int); var s1 []*(Int); func inc2(j *(Int)) { *(j) = *(j) + (const (2 main.Int)) }; func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 main.Int)); i<~VPBlock(1,0)> < (const (10 main.Int)); inc2(&(i<~VPBlock(1,0)>)) { s1 = (const (append func(x []*main.Int,args ...*main.Int)(res []*main.Int)))(s1, &(i<~VPBlock(1,0)>)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 10 +// s1[1] is: 10 +// s1[2] is: 10 +// s1[3] is: 10 +// s1[4] is: 10 diff --git a/gnovm/tests/files/heap_alloc_forloop1b.gno b/gnovm/tests/files/heap_alloc_forloop1b.gno new file mode 100644 index 000000000000..35b167e41688 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop1b.gno @@ -0,0 +1,37 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + r := i + r, ok := 0, true + println(ok, r) + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { r := i<~VPBlock(1,0)>; r, ok := (const (0 int)), (const (true bool)); (const (println func(xs ...interface{})()))(ok, r); s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(i<~VPBlock(1,0)>)) } }; func main() { forLoopRef() } } + +// Output: +// true 0 +// true 0 +// true 0 +// s1[0] is: 3 +// s1[1] is: 3 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop2.gno b/gnovm/tests/files/heap_alloc_forloop2.gno new file mode 100644 index 000000000000..aa7f6e44dd3a --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop2.gno @@ -0,0 +1,33 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + z := i + 1 + s1 = append(s1, &z) + } +} + +func main() { + forLoopRef() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<~...>. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i < (const (3 int)); i++ { z := i + (const (1 int)); s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(z<~VPBlock(1,1)>)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 1 +// s1[1] is: 2 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop2a.gno b/gnovm/tests/files/heap_alloc_forloop2a.gno new file mode 100644 index 000000000000..be4b089ccad4 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop2a.gno @@ -0,0 +1,34 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + z := i + s1 = append(s1, &z) + z++ + } +} + +func main() { + forLoopRef() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<~...>. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i < (const (3 int)); i++ { z := i; s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(z<~VPBlock(1,1)>)); z<~VPBlock(1,1)>++ } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 1 +// s1[1] is: 2 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop3.gno b/gnovm/tests/files/heap_alloc_forloop3.gno new file mode 100644 index 000000000000..91c9b6271204 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop3.gno @@ -0,0 +1,33 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + z := i + fs = append(fs, func() { println(z) }) + } +} + +func main() { + forLoopClosure() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<()~...>. + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i < (const (3 int)); i++ { z := i; fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop3a.gno b/gnovm/tests/files/heap_alloc_forloop3a.gno new file mode 100644 index 000000000000..fd361e7134e7 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop3a.gno @@ -0,0 +1,38 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + x := i + println(x) + z := i + fs = append(fs, func() { println(z) }) + } +} + +func main() { + forLoopClosure() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<()~...>. + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i < (const (3 int)); i++ { x := i; (const (println func(xs ...interface{})()))(x); z := i; fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 0 +// 1 +// 2 +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop4.gno b/gnovm/tests/files/heap_alloc_forloop4.gno new file mode 100644 index 000000000000..3cddb1a60fed --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop4.gno @@ -0,0 +1,31 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + fs = append(fs, func() { println(i) }) + } +} + +func main() { + forLoopClosure() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ (const (println func(xs ...interface{})()))(i<~VPBlock(1,0)>) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 3 +// 3 +// 3 diff --git a/gnovm/tests/files/heap_alloc_forloop5.gno b/gnovm/tests/files/heap_alloc_forloop5.gno new file mode 100644 index 000000000000..4f563ec866ba --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop5.gno @@ -0,0 +1,32 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + fs = append(fs, func() { + z := i + println(z) + }) + } +} + +func main() { + forLoopClosure() +} + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ z := i<~VPBlock(1,1)>; (const (println func(xs ...interface{})()))(z) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 3 +// 3 +// 3 diff --git a/gnovm/tests/files/heap_alloc_forloop5a.gno b/gnovm/tests/files/heap_alloc_forloop5a.gno new file mode 100644 index 000000000000..039be2b86a8a --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop5a.gno @@ -0,0 +1,33 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + x := i + fs = append(fs, func() { + z := x + println(z) + }) + } +} + +func main() { + forLoopClosure() +} + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i < (const (3 int)); i++ { x := i; fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ z := x<~VPBlock(1,1)>; (const (println func(xs ...interface{})()))(z) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6.gno b/gnovm/tests/files/heap_alloc_forloop6.gno new file mode 100644 index 000000000000..6cfa8a65fc8f --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 3; i++ { + z := i + f := func() int { + return z + } + fns = append(fns, f) + } + + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (3 int)); i++ { z := i; f := func func() (const-type int){ return z<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6a.gno b/gnovm/tests/files/heap_alloc_forloop6a.gno new file mode 100644 index 000000000000..6365fcd8c622 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 5; i++ { + f := func() int { + return i + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (5 int)); i<~VPBlock(1,0)>++ { f := func func() (const-type int){ return i<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 5 +// 5 +// 5 +// 5 +// 5 diff --git a/gnovm/tests/files/heap_alloc_forloop6b.gno b/gnovm/tests/files/heap_alloc_forloop6b.gno new file mode 100644 index 000000000000..73d9e5cd6a7a --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6b.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + x := i + y := 0 + f := func() int { + x += y + x += 1 + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; y := (const (0 int)); f := func func() (const-type int){ x<~VPBlock(1,1)> += y<~VPBlock(1,2)>; x<~VPBlock(1,1)> += (const (1 int)); return x<~VPBlock(1,1)> }, y<()~VPBlock(1,2)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6c.gno b/gnovm/tests/files/heap_alloc_forloop6c.gno new file mode 100644 index 000000000000..f8d2d410f6c7 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6c.gno @@ -0,0 +1,23 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + f := func() int { + return i + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (2 int)); i<~VPBlock(1,0)>++ { f := func func() (const-type int){ return i<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 2 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6f.gno b/gnovm/tests/files/heap_alloc_forloop6f.gno new file mode 100644 index 000000000000..fcc2cdfdcc15 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6f.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 5; i++ { + var x int + f := func() int { + return x + } + x = i + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (5 int)); i++ { var x (const-type int); f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; x<~VPBlock(1,1)> = i; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop6g.gno b/gnovm/tests/files/heap_alloc_forloop6g.gno new file mode 100644 index 000000000000..4ff7856c97c0 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6g.gno @@ -0,0 +1,27 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 5; i++ { + x := i + { // another block + f := func() int { + return x + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (5 int)); i++ { x := i; { f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop6h.gno b/gnovm/tests/files/heap_alloc_forloop6h.gno new file mode 100644 index 000000000000..75b84bebf91b --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6h.gno @@ -0,0 +1,33 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + x := i + for j := 0; j < 2; j++ { + y := j + f := func() int { + return x + y + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; for j := (const (0 int)); j < (const (2 int)); j++ { y := j; f := func func() (const-type int){ return x<~VPBlock(1,1)> + y<~VPBlock(1,2)> }, y<()~VPBlock(1,1)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Go Output: +// 0 +// 1 +// 1 +// 2 + +// Output: +// 0 +// 1 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6h0.gno b/gnovm/tests/files/heap_alloc_forloop6h0.gno new file mode 100644 index 000000000000..0225bd62cf63 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6h0.gno @@ -0,0 +1,27 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + for j := 0; j < 2; j++ { + f := func() int { + return i + j + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (2 int)); i<~VPBlock(1,0)>++ { for j := (const (0 int)); j<~VPBlock(1,0)> < (const (2 int)); j<~VPBlock(1,0)>++ { f := func func() (const-type int){ return i<~VPBlock(1,1)> + j<~VPBlock(1,2)> }, j<()~VPBlock(1,0)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 4 +// 4 +// 4 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop6i.gno b/gnovm/tests/files/heap_alloc_forloop6i.gno new file mode 100644 index 000000000000..28bb17cbf5fe --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6i.gno @@ -0,0 +1,34 @@ +package main + +func main() { + var fns []func() int + var x int + for i := 0; i < 2; i++ { + x = i + for j := 0; j < 2; j++ { + y := j + f := func() int { + return x + y + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); var x (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x = i; for j := (const (0 int)); j < (const (2 int)); j++ { y := j; f := func func() (const-type int){ return x + y<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Go Output: +// 1 +// 2 +// 1 +// 2 + +// Output: +// 1 +// 2 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop7.gno b/gnovm/tests/files/heap_alloc_forloop7.gno new file mode 100644 index 000000000000..95fdf42045d6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop7.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + if true { + if true { + return x + } + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ if (const (true bool)) { if (const (true bool)) { return x<~VPBlock(3,1)> } }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop7a.gno b/gnovm/tests/files/heap_alloc_forloop7a.gno new file mode 100644 index 000000000000..59e83022f576 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop7a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + if true { + return x + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ if (const (true bool)) { return x<~VPBlock(2,1)> }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop8.gno b/gnovm/tests/files/heap_alloc_forloop8.gno new file mode 100644 index 000000000000..7c86fdc5b906 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + { + return x + } + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ { return x<~VPBlock(2,1)> } }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop8a.gno b/gnovm/tests/files/heap_alloc_forloop8a.gno new file mode 100644 index 000000000000..f0864fa07da4 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + for i := 0; i < 1; i++ { + x++ + } + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ for i := (const (0 int)); i < (const (1 int)); i++ { x<~VPBlock(2,1)>++ }; return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop8b.gno b/gnovm/tests/files/heap_alloc_forloop8b.gno new file mode 100644 index 000000000000..1cd6bf13cc32 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8b.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + s := []int{1, 2} + + f := func() int { + for _, v := range s { + x += v + } + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; s := [](const-type int){(const (1 int)), (const (2 int))}; f := func func() (const-type int){ for _, v := range s<~VPBlock(2,1)> { x<~VPBlock(2,2)> += v }; return x<~VPBlock(1,2)> }, x<()~VPBlock(1,1)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop8c.gno b/gnovm/tests/files/heap_alloc_forloop8c.gno new file mode 100644 index 000000000000..11aef1683b88 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8c.gno @@ -0,0 +1,30 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + y := 1 + f := func() int { + switch y { + case 1: + x += 1 + default: + x += 0 + } + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; y := (const (1 int)); f := func func() (const-type int){ switch y<~VPBlock(2,1)> { case (const (1 int)): x<~VPBlock(2,2)> += (const (1 int)); default: x<~VPBlock(2,2)> += (const (0 int)) }; return x<~VPBlock(1,2)> }, x<()~VPBlock(1,1)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop9.gno b/gnovm/tests/files/heap_alloc_forloop9.gno new file mode 100644 index 000000000000..0f1d0b8b23c8 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9.gno @@ -0,0 +1,42 @@ +package main + +import "fmt" + +// recursive closure does not capture +func main() { + var fns []func(int) int + var recursiveFunc func(int) int + + for i := 0; i < 3; i++ { + recursiveFunc = func(num int) int { + x := i + println("value of x: ", x) + if num <= 0 { + return 1 + } + return num * recursiveFunc(num-1) + } + fns = append(fns, recursiveFunc) + } + + for i, r := range fns { + result := r(i) + fmt.Printf("Factorial of %d is: %d\n", i, result) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { var fns []func(.arg_0 (const-type int)) (const-type int); var recursiveFunc func(.arg_0 (const-type int)) (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { recursiveFunc = func func(num (const-type int)) (const-type int){ x := i<~VPBlock(1,3)>; (const (println func(xs ...interface{})()))((const ("value of x: " string)), x); if num <= (const (0 int)) { return (const (1 int)) }; return num * recursiveFunc(num - (const (1 int))) }>; fns = (const (append func(x []func(.arg_0 int)( int),args ...func(.arg_0 int)( int))(res []func(.arg_0 int)( int))))(fns, recursiveFunc) }; for i, r := range fns { result := r(i); fmt.Printf((const ("Factorial of %d is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(result)) } } } + +// Output: +// value of x: 3 +// Factorial of 0 is: 1 +// value of x: 3 +// value of x: 3 +// Factorial of 1 is: 1 +// value of x: 3 +// value of x: 3 +// value of x: 3 +// Factorial of 2 is: 2 diff --git a/gnovm/tests/files/heap_alloc_forloop9_1.gno b/gnovm/tests/files/heap_alloc_forloop9_1.gno new file mode 100644 index 000000000000..5e3b9af74f65 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9_1.gno @@ -0,0 +1,25 @@ +package main + +func Search(n int, f func(int) bool) int { + f(1) + return 0 +} + +// TODO: identify this pattern, optimize. +func main() { + for x := 0; x < 2; x++ { + count := 0 + println(" first: count: ", count) + Search(1, func(i int) bool { count++; return i >= x }) + println("second: count: ", count) + } +} + +// Preprocessed: +// file{ package main; func Search(n (const-type int), f func(.arg_0 (const-type int)) (const-type bool)) (const-type int) { f((const (1 int))); return (const (0 int)) }; func main() { for x := (const (0 int)); x<~VPBlock(1,0)> < (const (2 int)); x<~VPBlock(1,0)>++ { count := (const (0 int)); (const (println func(xs ...interface{})()))((const (" first: count: " string)), count<~VPBlock(1,1)>); Search((const (1 int)), func func(i (const-type int)) (const-type bool){ count<~VPBlock(1,2)>++; return (const-type bool)(i >= x<~VPBlock(1,3)>) }, x<()~VPBlock(1,0)>>); (const (println func(xs ...interface{})()))((const ("second: count: " string)), count<~VPBlock(1,1)>) } } } + +// Output: +// first: count: 0 +// second: count: 1 +// first: count: 0 +// second: count: 1 diff --git a/gnovm/tests/files/heap_alloc_forloop9_2.gno b/gnovm/tests/files/heap_alloc_forloop9_2.gno new file mode 100644 index 000000000000..6b1ebdbb7e9c --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9_2.gno @@ -0,0 +1,36 @@ +package main + +func main() { + var fns []func() int + + println("start for loop") + for i := 0; i < 2; i++ { + defer func() { + println("defer") + for _, fn := range fns { + println(fn()) + } + }() + + x := i + f := func() int { + return x + } + + fns = append(fns, f) + } + println("end for loop") +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); (const (println func(xs ...interface{})()))((const ("start for loop" string))); for i := (const (0 int)); i < (const (2 int)); i++ { defer func func(){ (const (println func(xs ...interface{})()))((const ("defer" string))); for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } }(); x := i; f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; (const (println func(xs ...interface{})()))((const ("end for loop" string))) } } + +// Output: +// start for loop +// end for loop +// defer +// 0 +// 1 +// defer +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop9b.gno b/gnovm/tests/files/heap_alloc_forloop9b.gno new file mode 100644 index 000000000000..03e84fcd2b21 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9b.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var y int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + for i := 0; i < 2; i++ { + for j := 0; j < 2; j++ { + x := y + f = append(f, func() { println(x) }) + y++ + } + } +} + +// Preprocessed: +// file{ package main; func main() { var y (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); for i := (const (0 int)); i < (const (2 int)); i++ { for j := (const (0 int)); j < (const (2 int)); j++ { x := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++ } } } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop0.gno b/gnovm/tests/files/heap_alloc_gotoloop0.gno new file mode 100644 index 000000000000..d13baedf7c42 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop0.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + // this is actually an implicit for loop +LABEL_1: + if counter == 2 { + return + } + x := counter + f = append(f, func() { println(x) }) + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); if counter == (const (2 int)) { return }; x := counter; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop1.gno b/gnovm/tests/files/heap_alloc_gotoloop1.gno new file mode 100644 index 000000000000..ea26952e0a42 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop1.gno @@ -0,0 +1,30 @@ +package main + +func main() { + c := 0 +loop: + i := 1 + println(i) + c += 1 + if c < 10 { + goto loop + } +} + +// This does not make 'i' NameExprTypeHeapDefine, +// because it is not actually used in a &ref or closure context. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); i := (const (1 int)); (const (println func(xs ...interface{})()))(i); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,1> } } } + +// Output: +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop2.gno b/gnovm/tests/files/heap_alloc_gotoloop2.gno new file mode 100644 index 000000000000..e7b2917a8ff2 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop2.gno @@ -0,0 +1,37 @@ +package main + +func main() { + c := 0 + closures := []func(){} +loop: + i := c + closures = append(closures, func() { + println(i) + }) + c += 1 + if c < 10 { + goto loop + } + + for _, cl := range closures { + cl() + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<()~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); closures := []func(){}; i := c; closures = (const (append func(x []func()(),args ...func()())(res []func()())))(closures, func func(){ (const (println func(xs ...interface{})()))(i<~VPBlock(1,0)>) }>); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, cl := range closures { cl() } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 diff --git a/gnovm/tests/files/heap_alloc_gotoloop3.gno b/gnovm/tests/files/heap_alloc_gotoloop3.gno new file mode 100644 index 000000000000..a248e8aa0bce --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop3.gno @@ -0,0 +1,34 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + i := c + refs = append(refs, &i) + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; i := c; refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 diff --git a/gnovm/tests/files/heap_alloc_gotoloop4.gno b/gnovm/tests/files/heap_alloc_gotoloop4.gno new file mode 100644 index 000000000000..062d832ac167 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop4.gno @@ -0,0 +1,34 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + var i int = c + refs = append(refs, &i) + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; var i (const-type int) = c; refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 diff --git a/gnovm/tests/files/heap_alloc_gotoloop5.gno b/gnovm/tests/files/heap_alloc_gotoloop5.gno new file mode 100644 index 000000000000..fb7a82228f12 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop5.gno @@ -0,0 +1,39 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + i, j := c, 2 + refs = append(refs, &i) + i += 1 + j += 1 + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } + if false { + println(j) // dummy usage + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; i, j := c, (const (2 int)); refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); i<~VPBlock(1,2)> += (const (1 int)); j += (const (1 int)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) }; if (const (false bool)) { (const (println func(xs ...interface{})()))(j) } } } + +// Output: +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 diff --git a/gnovm/tests/files/heap_alloc_gotoloop6.gno b/gnovm/tests/files/heap_alloc_gotoloop6.gno new file mode 100644 index 000000000000..d2efbb85df20 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop6.gno @@ -0,0 +1,39 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + var i, j int = c, 2 + refs = append(refs, &i) + i += 1 + j += 1 + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } + if false { + println(j) // dummy usage + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; var i, j (const-type int) = c, (const (2 int)); refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); i<~VPBlock(1,2)> += (const (1 int)); j += (const (1 int)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) }; if (const (false bool)) { (const (println func(xs ...interface{})()))(j) } } } + +// Output: +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 diff --git a/gnovm/tests/files/heap_alloc_gotoloop7.gno b/gnovm/tests/files/heap_alloc_gotoloop7.gno new file mode 100644 index 000000000000..457fdb74a01d --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop7.gno @@ -0,0 +1,48 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + var i, j int = c, 2 + refs = append(refs, &i) + i += 1 + j += 1 + c += 1 + thing := func() { + i := 2 // new i + j := 3 // new j + println(i) + println(j) + } + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } + if false { + println(j) // dummy usage + } + if false { + thing() // dummy usage + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; var i, j (const-type int) = c, (const (2 int)); refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); i<~VPBlock(1,2)> += (const (1 int)); j += (const (1 int)); c += (const (1 int)); thing := func func(){ i := (const (2 int)); j := (const (3 int)); (const (println func(xs ...interface{})()))(i); (const (println func(xs ...interface{})()))(j) }; if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) }; if (const (false bool)) { (const (println func(xs ...interface{})()))(j) }; if (const (false bool)) { thing() } } } + +// Output: +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 diff --git a/gnovm/tests/files/heap_alloc_gotoloop8.gno b/gnovm/tests/files/heap_alloc_gotoloop8.gno new file mode 100644 index 000000000000..f3421048d411 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop8.gno @@ -0,0 +1,37 @@ +package main + +func main() { + c := 0 + closures := []func(){} + goto loop1 +loop1: // not a loop + i := 1 +loop2: + closures = append(closures, func() { + println(i) + }) + c += 1 + if c < 10 { + goto loop2 + } + for _, cl := range closures { + cl() + } +} + +// This one doesn't because the goto stmt doesn't go back far enough. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); closures := []func(){}; goto loop1<0,3>; i := (const (1 int)); closures = (const (append func(x []func()(),args ...func()())(res []func()())))(closures, func func(){ (const (println func(xs ...interface{})()))(i) }); c += (const (1 int)); if c < (const (10 int)) { goto loop2<1,4> }; for _, cl := range closures { cl() } } } + +// Output: +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9.gno b/gnovm/tests/files/heap_alloc_gotoloop9.gno new file mode 100644 index 000000000000..382046522160 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9.gno @@ -0,0 +1,35 @@ +package main + +func main() { + c := 0 + closures := []func(){} + i := 1 +loop2: + closures = append(closures, func() { + println(i) + }) + c += 1 + if c < 10 { + goto loop2 + } + for _, cl := range closures { + cl() + } +} + +// This one doesn't because the goto stmt doesn't go back far enough. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); closures := []func(){}; i := (const (1 int)); closures = (const (append func(x []func()(),args ...func()())(res []func()())))(closures, func func(){ (const (println func(xs ...interface{})()))(i) }); c += (const (1 int)); if c < (const (10 int)) { goto loop2<1,3> }; for _, cl := range closures { cl() } } } + +// Output: +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_10.gno b/gnovm/tests/files/heap_alloc_gotoloop9_10.gno new file mode 100644 index 000000000000..bb8a2bad3eff --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_10.gno @@ -0,0 +1,64 @@ +package main + +import "fmt" + +var s1 []*int +var s2 []*int + +// intersection loop +func main() { + defer func() { + for i, v := range s1 { + fmt.Printf("s1[%d] is %d\n", i, *v) + } + for i, v := range s2 { + fmt.Printf("s2[%d] is %d\n", i, *v) + } + }() + + // counter for loop + var c1, c2 int + +LOOP_1: + x := c1 + s1 = append(s1, &x) + println("loop_1", c1) + c1++ + +LOOP_2: + y := c2 + s2 = append(s2, &y) + println("loop_2", c2) + c2++ + + if c1 < 3 { + goto LOOP_1 + } + + if c2 < 6 { + goto LOOP_2 + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); var s2 []*((const-type int)); func main() { defer func func(){ for i, v := range s1 { fmt.Printf((const ("s1[%d] is %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(v))) }; for i, v := range s2 { fmt.Printf((const ("s2[%d] is %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(v))) } }(); var c1, c2 (const-type int); x := c1; s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(x<~VPBlock(1,2)>)); (const (println func(xs ...interface{})()))((const ("loop_1" string)), c1); c1++; y := c2; s2 = (const (append func(x []*int,args ...*int)(res []*int)))(s2, &(y<~VPBlock(1,3)>)); (const (println func(xs ...interface{})()))((const ("loop_2" string)), c2); c2++; if c1 < (const (3 int)) { goto LOOP_1<1,2> }; if c2 < (const (6 int)) { goto LOOP_2<1,6> } } } + +// Output: +// loop_1 0 +// loop_2 0 +// loop_1 1 +// loop_2 1 +// loop_1 2 +// loop_2 2 +// loop_2 3 +// loop_2 4 +// loop_2 5 +// s1[0] is 0 +// s1[1] is 1 +// s1[2] is 2 +// s2[0] is 0 +// s2[1] is 1 +// s2[2] is 2 +// s2[3] is 3 +// s2[4] is 4 +// s2[5] is 5 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_11.gno b/gnovm/tests/files/heap_alloc_gotoloop9_11.gno new file mode 100644 index 000000000000..839612704a80 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_11.gno @@ -0,0 +1,29 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + // this is actually an implicit for loop +LABEL_1: + if counter == 2 { + return + } + var _, x = 0, y + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); if counter == (const (2 int)) { return }; var _, x = (const (0 int)), y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_12.gno b/gnovm/tests/files/heap_alloc_gotoloop9_12.gno new file mode 100644 index 000000000000..4d024a58673a --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_12.gno @@ -0,0 +1,56 @@ +package main + +import "fmt" + +func main() { + counter0 := 0 + counter1 := 0 + + y := 0 + + var fs []func() + + defer func() { + for _, ff := range fs { + ff() + } + }() + +LOOP_START: + if counter0 < 2 { + counter1 = 0 + fmt.Printf("Outer loop start: counter0=%d\n", counter0) + + NESTED_LOOP_START: + if counter1 < 2 { + fmt.Printf(" Nested loop: counter1=%d\n", counter1) + counter1++ + goto NESTED_LOOP_START + } + + x := y + fs = append(fs, func() { println(x) }) + + fmt.Println("Exiting nested loop") + counter0++ + y++ + goto LOOP_START + } else { + return + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { counter0 := (const (0 int)); counter1 := (const (0 int)); y := (const (0 int)); var fs []func(); defer func func(){ for _, ff := range fs { ff() } }(); if counter0 < (const (2 int)) { counter1 = (const (0 int)); fmt.Printf((const ("Outer loop start: counter0=%d\n" string)), (const-type gonative{interface {}})(counter0)); if counter1 < (const (2 int)) { fmt.Printf((const (" Nested loop: counter1=%d\n" string)), (const-type gonative{interface {}})(counter1)); counter1++; goto NESTED_LOOP_START<1,2> }; x := y; fs = (const (append func(x []func()(),args ...func()())(res []func()())))(fs, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); fmt.Println((const ("Exiting nested loop" string))); counter0++; y++; goto LOOP_START<1,5> } else { return } } } + +// Output: +// Outer loop start: counter0=0 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// Outer loop start: counter0=1 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_13.gno b/gnovm/tests/files/heap_alloc_gotoloop9_13.gno new file mode 100644 index 000000000000..7c7b67772235 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_13.gno @@ -0,0 +1,41 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + +LABEL_1: + x := y + if counter == 2 { + counter = 0 + goto LABEL_2 + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + +LABEL_2: + if counter == 2 { + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); x := y; if counter == (const (2 int)) { counter = (const (0 int)); goto LABEL_2<1,9> }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,3>; if counter == (const (2 int)) { return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,9> } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_14.gno b/gnovm/tests/files/heap_alloc_gotoloop9_14.gno new file mode 100644 index 000000000000..f92b31eb7de6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_14.gno @@ -0,0 +1,43 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + { + LABEL_1: + x := y + if counter == 2 { + counter = 0 + goto LABEL_2 + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + } + +LABEL_2: + if counter == 2 { + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); { x := y; if counter == (const (2 int)) { counter = (const (0 int)); goto LABEL_2<2,4> }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,0> }; if counter == (const (2 int)) { return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,4> } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_15.gno b/gnovm/tests/files/heap_alloc_gotoloop9_15.gno new file mode 100644 index 000000000000..d774af55eb66 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_15.gno @@ -0,0 +1,48 @@ +package main + +var y, counter int +var f []func() + +func main() { + defer func() { + for _, ff := range f { // XXX, why defer on this not work + ff() + } + }() +LABEL_1: + x := y + if counter == 2 { + counter = 0 + bar() + return + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 +} + +func bar() { + println("---bar---") +LABEL_2: + if counter == 2 { + println("---end---") + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; var y, counter (const-type int); var f []func(); func main() { defer func func(){ for _, ff := range f { ff() } }(); x := y; if counter == (const (2 int)) { counter = (const (0 int)); bar(); return }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,1> }; func bar() { (const (println func(xs ...interface{})()))((const ("---bar---" string))); if counter == (const (2 int)) { (const (println func(xs ...interface{})()))((const ("---end---" string))); return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,1> } } + +// Output: +// ---bar--- +// ---end--- +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_15a.gno b/gnovm/tests/files/heap_alloc_gotoloop9_15a.gno new file mode 100644 index 000000000000..2d9de02ecc34 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_15a.gno @@ -0,0 +1,46 @@ +package main + +var y, counter int +var f []func() + +func main() { +LABEL_1: + x := y + if counter == 2 { + counter = 0 + bar() + for _, ff := range f { // XXX, why defer on this not work + ff() + } + return + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 +} + +func bar() { + println("---bar---") +LABEL_2: + if counter == 2 { + println("---end---") + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; var y, counter (const-type int); var f []func(); func main() { x := y; if counter == (const (2 int)) { counter = (const (0 int)); bar(); for _, ff := range f { ff() }; return }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,0> }; func bar() { (const (println func(xs ...interface{})()))((const ("---bar---" string))); if counter == (const (2 int)) { (const (println func(xs ...interface{})()))((const ("---end---" string))); return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,1> } } + +// Output: +// ---bar--- +// ---end--- +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_16.gno b/gnovm/tests/files/heap_alloc_gotoloop9_16.gno new file mode 100644 index 000000000000..8971b04aee6a --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_16.gno @@ -0,0 +1,58 @@ +package main + +import "fmt" + +func main() { + counter0 := 0 + counter1 := 0 + + y := 0 + + var fs []func() + + defer func() { + for _, ff := range fs { + ff() + } + }() + +LOOP_START: + if counter0 < 2 { + x := y + counter1 = 0 + fmt.Printf("Outer loop start: counter0=%d\n", counter0) + + NESTED_LOOP_START: + if counter1 < 2 { + fmt.Printf(" Nested loop: counter1=%d\n", counter1) + fs = append(fs, func() { println(x) }) + + counter1++ + goto NESTED_LOOP_START + } + + fmt.Println("Exiting nested loop") + counter0++ + y++ + goto LOOP_START + } else { + return + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { counter0 := (const (0 int)); counter1 := (const (0 int)); y := (const (0 int)); var fs []func(); defer func func(){ for _, ff := range fs { ff() } }(); if counter0 < (const (2 int)) { x := y; counter1 = (const (0 int)); fmt.Printf((const ("Outer loop start: counter0=%d\n" string)), (const-type gonative{interface {}})(counter0)); if counter1 < (const (2 int)) { fmt.Printf((const (" Nested loop: counter1=%d\n" string)), (const-type gonative{interface {}})(counter1)); fs = (const (append func(x []func()(),args ...func()())(res []func()())))(fs, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter1++; goto NESTED_LOOP_START<1,3> }; fmt.Println((const ("Exiting nested loop" string))); counter0++; y++; goto LOOP_START<1,5> } else { return } } } + +// Output: +// Outer loop start: counter0=0 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// Outer loop start: counter0=1 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// 0 +// 0 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_17.gno b/gnovm/tests/files/heap_alloc_gotoloop9_17.gno new file mode 100644 index 000000000000..9e5073c1bfea --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_17.gno @@ -0,0 +1,58 @@ +package main + +import "fmt" + +func main() { + counter0 := 0 + counter1 := 0 + + y := 0 + + var fs []func() + + defer func() { + for _, ff := range fs { + ff() + } + }() + +LOOP_START: + x := y + if counter0 < 2 { + counter1 = 0 + fmt.Printf("Outer loop start: counter0=%d\n", counter0) + + NESTED_LOOP_START: + if counter1 < 2 { + fmt.Printf(" Nested loop: counter1=%d\n", counter1) + fs = append(fs, func() { println(x) }) + + counter1++ + goto NESTED_LOOP_START + } + + fmt.Println("Exiting nested loop") + counter0++ + y++ + goto LOOP_START + } else { + return + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { counter0 := (const (0 int)); counter1 := (const (0 int)); y := (const (0 int)); var fs []func(); defer func func(){ for _, ff := range fs { ff() } }(); x := y; if counter0 < (const (2 int)) { counter1 = (const (0 int)); fmt.Printf((const ("Outer loop start: counter0=%d\n" string)), (const-type gonative{interface {}})(counter0)); if counter1 < (const (2 int)) { fmt.Printf((const (" Nested loop: counter1=%d\n" string)), (const-type gonative{interface {}})(counter1)); fs = (const (append func(x []func()(),args ...func()())(res []func()())))(fs, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter1++; goto NESTED_LOOP_START<1,2> }; fmt.Println((const ("Exiting nested loop" string))); counter0++; y++; goto LOOP_START<1,5> } else { return } } } + +// Output: +// Outer loop start: counter0=0 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// Outer loop start: counter0=1 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// 0 +// 0 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_18.gno b/gnovm/tests/files/heap_alloc_gotoloop9_18.gno new file mode 100644 index 000000000000..1578eb5897fd --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_18.gno @@ -0,0 +1,30 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + { + LABEL_1: + if counter == 2 { + return + } + x := y + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + } +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); { if counter == (const (2 int)) { return }; x := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,0> } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_19.gno b/gnovm/tests/files/heap_alloc_gotoloop9_19.gno new file mode 100644 index 000000000000..fb1b995372ec --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_19.gno @@ -0,0 +1,30 @@ +package main + +func main() { + var y, counter int + var f []func() func() int + defer func() { + for _, ff := range f { + println(ff()()) + } + }() + +LABEL_1: + if counter == 2 { + return + } + x := y + f = append(f, func() func() int { + return func() int { return x } + }) + y++ + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func() func() (const-type int); defer func func(){ for _, ff := range f { (const (println func(xs ...interface{})()))(ff()()) } }(); if counter == (const (2 int)) { return }; x := y; f = (const (append func(x []func()( func()( int)),args ...func()( func()( int)))(res []func()( func()( int)))))(f, func func() func() (const-type int){ return func func() (const-type int){ return x<~VPBlock(2,1)> } }>); y++; counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_20.gno b/gnovm/tests/files/heap_alloc_gotoloop9_20.gno new file mode 100644 index 000000000000..04896b425a54 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_20.gno @@ -0,0 +1,32 @@ +package main + +func main() { + var y, counter int + var f []func() (int, func() int) + defer func() { + for _, ff := range f { + n, f := ff() + println(n + f()) + } + }() + +LABEL_1: + if counter == 2 { + return + } + x := y + z := y + f = append(f, func() (int, func() int) { + return z, func() int { return x } + }) + y++ + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func() (const-type int), func() (const-type int); defer func func(){ for _, ff := range f { n, f := ff(); (const (println func(xs ...interface{})()))(n + f()) } }(); if counter == (const (2 int)) { return }; x := y; z := y; f = (const (append func(x []func()( int, func()( int)),args ...func()( int, func()( int)))(res []func()( int, func()( int)))))(f, func func() (const-type int), func() (const-type int){ return z<~VPBlock(1,2)>, func func() (const-type int){ return x<~VPBlock(2,3)> } }, x<()~VPBlock(1,3)>>); y++; counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 2 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_21.gno b/gnovm/tests/files/heap_alloc_gotoloop9_21.gno new file mode 100644 index 000000000000..fa27f3376e05 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_21.gno @@ -0,0 +1,31 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + f1 := func() { + LABEL_1: + if counter == 2 { + return + } + x := counter + f = append(f, func() { println(x) }) + counter++ + goto LABEL_1 + } + + f1() +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); f1 := func func(){ if counter == (const (2 int)) { return }; x := counter; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter++; goto LABEL_1<0,0> }; f1() } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_21a.gno b/gnovm/tests/files/heap_alloc_gotoloop9_21a.gno new file mode 100644 index 000000000000..48364ed40752 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_21a.gno @@ -0,0 +1,33 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + f1 := func() { + LABEL_1: + if counter == 2 { + return + } + x := counter + func() { + f = append(f, func() { println(x) }) + }() + counter++ + goto LABEL_1 + } + + f1() +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); f1 := func func(){ if counter == (const (2 int)) { return }; x := counter; func func(){ f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(2,0)>) }) }>(); counter++; goto LABEL_1<0,0> }; f1() } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_21b.gno b/gnovm/tests/files/heap_alloc_gotoloop9_21b.gno new file mode 100644 index 000000000000..8758608a5e63 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_21b.gno @@ -0,0 +1,34 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + f1 := func() { + LABEL_1: + if counter == 2 { + return + } + + func() { + x := counter + f = append(f, func() { println(x) }) + }() + counter++ + goto LABEL_1 + } + + f1() +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); f1 := func func(){ if counter == (const (2 int)) { return }; func func(){ x := counter; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x) }) }(); counter++; goto LABEL_1<0,0> }; f1() } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_22.gno b/gnovm/tests/files/heap_alloc_gotoloop9_22.gno new file mode 100644 index 000000000000..cd283345869a --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_22.gno @@ -0,0 +1,33 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + for i := 0; i < 2; i++ { + counter = 0 + LABEL_1: + if counter == 2 { + continue + } + x := y + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + } +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); for i := (const (0 int)); i < (const (2 int)); i++ { counter = (const (0 int)); if counter == (const (2 int)) { continue }; x := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,1> } } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_range1.gno b/gnovm/tests/files/heap_alloc_range1.gno new file mode 100644 index 000000000000..34520729a067 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range1.gno @@ -0,0 +1,30 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + s := []int{0, 1, 2} + for i, _ := range s { + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); s := [](const-type int){(const (0 int)), (const (1 int)), (const (2 int))}; for i, _ := range s { s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(i)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 2 +// s1[1] is: 2 +// s1[2] is: 2 diff --git a/gnovm/tests/files/heap_alloc_range2.gno b/gnovm/tests/files/heap_alloc_range2.gno new file mode 100644 index 000000000000..34b7cc527afc --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range2.gno @@ -0,0 +1,30 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + s := []int{0, 1, 2} + for _, v := range s { + s1 = append(s1, &v) + } +} + +func main() { + forLoopRef() +} + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); s := [](const-type int){(const (0 int)), (const (1 int)), (const (2 int))}; for _, v := range s { s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(v)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 2 +// s1[1] is: 2 +// s1[2] is: 2 diff --git a/gnovm/tests/files/heap_alloc_range3.gno b/gnovm/tests/files/heap_alloc_range3.gno new file mode 100644 index 000000000000..032d0cf8b6d7 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range3.gno @@ -0,0 +1,23 @@ +package main + +func main() { + s := []int{1, 2} + + f := func() { + for i, v := range s { + println(i) + println(v) + } + } + + f() +} + +// Preprocessed: +// file{ package main; func main() { s := [](const-type int){(const (1 int)), (const (2 int))}; f := func func(){ for i, v := range s { (const (println func(xs ...interface{})()))(i); (const (println func(xs ...interface{})()))(v) } }; f() } } + +// Output: +// 0 +// 1 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4.gno b/gnovm/tests/files/heap_alloc_range4.gno new file mode 100644 index 000000000000..2418184caca8 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4.gno @@ -0,0 +1,24 @@ +package main + +func main() { + var fns []func() int + s := []int{1, 2, 3} + for i, _ := range s { + x := i + f := func() int { + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); s := [](const-type int){(const (1 int)), (const (2 int)), (const (3 int))}; for i, _ := range s { x := i; f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4a.gno b/gnovm/tests/files/heap_alloc_range4a.gno new file mode 100644 index 000000000000..229d59d6011e --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + m := map[string]int{"a": 1, "b": 2} + for _, v := range m { + x := v + f := func() int { + if true { + return x + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); m := map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))}; for _, v := range m { x := v; f := func func() (const-type int){ if (const (true bool)) { return x<~VPBlock(2,1)> }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4a1.gno b/gnovm/tests/files/heap_alloc_range4a1.gno new file mode 100644 index 000000000000..7b126b0e5303 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4a1.gno @@ -0,0 +1,22 @@ +package main + +func main() { + var fns []func() int + m := map[string]int{"a": 1, "b": 2} + for _, v := range m { + f := func() int { + return v + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); m := map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))}; for _, v := range m { f := func func() (const-type int){ return v }; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 2 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4a2.gno b/gnovm/tests/files/heap_alloc_range4a2.gno new file mode 100644 index 000000000000..c54450f4619f --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4a2.gno @@ -0,0 +1,32 @@ +package main + +func main() { + var fns []func() int + y := 0 + m := map[string]int{"a": 1, "b": 2} + for _, v := range m { + x := v + f := func() int { + switch y { + case 0: + if true { + return x + } + default: + return 0 + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); y := (const (0 int)); m := map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))}; for _, v := range m { x := v; f := func func() (const-type int){ switch y { case (const (0 int)): if (const (true bool)) { return x<~VPBlock(3,1)> }; default: return (const (0 int)) }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4b.gno b/gnovm/tests/files/heap_alloc_range4b.gno new file mode 100644 index 000000000000..b4a380b361bc --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4b.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + s := "hello" + for i, _ := range s { + x := i + f := func() int { + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); s := (const ("hello" string)); for i, _ := range s { x := i; f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_range4b1.gno b/gnovm/tests/files/heap_alloc_range4b1.gno new file mode 100644 index 000000000000..24dd99ea98f0 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4b1.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + s := "hello" + for i, _ := range s { + f := func() int { + return i + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); s := (const ("hello" string)); for i, _ := range s { f := func func() (const-type int){ return i }; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 4 +// 4 +// 4 +// 4 +// 4 diff --git a/gnovm/tests/files/import6.gno b/gnovm/tests/files/import6.gno index 6909e1ad9232..f3cd9930eb5d 100644 --- a/gnovm/tests/files/import6.gno +++ b/gnovm/tests/files/import6.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// github.com/gnolang/gno/_test/c2/c2.gno:3:1: import cycle detected: "github.com/gnolang/gno/_test/c1" (through [github.com/gnolang/gno/_test/c1 github.com/gnolang/gno/_test/c2]) +// github.com/gnolang/gno/_test/c2/c2.gno:3:8: import cycle detected: "github.com/gnolang/gno/_test/c1" (through [github.com/gnolang/gno/_test/c1 github.com/gnolang/gno/_test/c2]) diff --git a/gnovm/tests/files/recursive1.gno b/gnovm/tests/files/recursive1.gno index 8279e247d84d..cd86d351dec6 100644 --- a/gnovm/tests/files/recursive1.gno +++ b/gnovm/tests/files/recursive1.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/recursive1.gno:1:1: invalid recursive type: S -> S +// main/files/recursive1.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive1c.gno b/gnovm/tests/files/recursive1c.gno index 7797f3750276..36237b039c06 100644 --- a/gnovm/tests/files/recursive1c.gno +++ b/gnovm/tests/files/recursive1c.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/recursive1c.gno:1:1: invalid recursive type: S -> S +// main/files/recursive1c.gno:5:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive1d.gno b/gnovm/tests/files/recursive1d.gno index 22bf172b5ac5..11c48bed3eb6 100644 --- a/gnovm/tests/files/recursive1d.gno +++ b/gnovm/tests/files/recursive1d.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/recursive1d.gno:1:1: invalid recursive type: S -> S +// main/files/recursive1d.gno:5:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive1f.gno b/gnovm/tests/files/recursive1f.gno index 81fe2a5699cb..7c6bc8f52fef 100644 --- a/gnovm/tests/files/recursive1f.gno +++ b/gnovm/tests/files/recursive1f.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/recursive1f.gno:3:1: invalid recursive type: S -> S +// main/files/recursive1f.gno:4:7: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive2.gno b/gnovm/tests/files/recursive2.gno index 4ed86f03d58a..f2382d7ce1a2 100644 --- a/gnovm/tests/files/recursive2.gno +++ b/gnovm/tests/files/recursive2.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/recursive2.gno:1:1: invalid recursive type: A -> B -> C -> A +// main/files/recursive2.gno:3:6: invalid recursive type: A -> B -> C -> A diff --git a/gnovm/tests/files/recursive2c.gno b/gnovm/tests/files/recursive2c.gno index 3b5c27ed8eae..d6068fba1bc5 100644 --- a/gnovm/tests/files/recursive2c.gno +++ b/gnovm/tests/files/recursive2c.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/recursive2c.gno:3:1: name B not defined in fileset with files [files/recursive2c.gno] +// main/files/recursive2c.gno:4:7: name B not defined in fileset with files [files/recursive2c.gno] diff --git a/gnovm/tests/files/recursive4a.gno b/gnovm/tests/files/recursive4a.gno index 8b4d13b47850..3d2b4e335904 100644 --- a/gnovm/tests/files/recursive4a.gno +++ b/gnovm/tests/files/recursive4a.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/recursive4a.gno:1:1: invalid recursive type: time -> time +// main/files/recursive4a.gno:3:6: invalid recursive type: time -> time diff --git a/gnovm/tests/files/recursive5.gno b/gnovm/tests/files/recursive5.gno index 1c2fbd89fb89..1498926f305b 100644 --- a/gnovm/tests/files/recursive5.gno +++ b/gnovm/tests/files/recursive5.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/recursive5.gno:1:1: invalid recursive type: S -> S +// main/files/recursive5.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive6a.gno b/gnovm/tests/files/recursive6a.gno index 8123fc626a55..a0791aca7f56 100644 --- a/gnovm/tests/files/recursive6a.gno +++ b/gnovm/tests/files/recursive6a.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/recursive6a.gno:1:1: invalid recursive type: SelfReferencing -> SelfReferencing +// main/files/recursive6a.gno:3:6: invalid recursive type: SelfReferencing -> SelfReferencing diff --git a/gnovm/tests/files/recursive7a.gno b/gnovm/tests/files/recursive7a.gno index b3c57516f138..b27a3a01324b 100644 --- a/gnovm/tests/files/recursive7a.gno +++ b/gnovm/tests/files/recursive7a.gno @@ -5,4 +5,4 @@ type S [2]S func main() {} // Error: -// main/files/recursive7a.gno:1:1: invalid recursive type: S -> S +// main/files/recursive7a.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive8.gno b/gnovm/tests/files/recursive8.gno index 1f9325ae35c2..afd5b44fcc64 100644 --- a/gnovm/tests/files/recursive8.gno +++ b/gnovm/tests/files/recursive8.gno @@ -5,4 +5,4 @@ type Int Int func main() {} // Error: -// main/files/recursive8.gno:1:1: invalid recursive type: Int -> Int +// main/files/recursive8.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9.gno b/gnovm/tests/files/recursive9.gno index 8181be55d335..3b930ee248d1 100644 --- a/gnovm/tests/files/recursive9.gno +++ b/gnovm/tests/files/recursive9.gno @@ -5,4 +5,4 @@ type Int = Int func main() {} // Error: -// main/files/recursive9.gno:1:1: invalid recursive type: Int -> Int +// main/files/recursive9.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9a.gno b/gnovm/tests/files/recursive9a.gno index b96efa090e4b..acd11893badc 100644 --- a/gnovm/tests/files/recursive9a.gno +++ b/gnovm/tests/files/recursive9a.gno @@ -5,4 +5,4 @@ type Int = *Int func main() {} // Error: -// main/files/recursive9a.gno:1:1: invalid recursive type: Int -> Int \ No newline at end of file +// main/files/recursive9a.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9b.gno b/gnovm/tests/files/recursive9b.gno index e033349d597d..3901099ec60b 100644 --- a/gnovm/tests/files/recursive9b.gno +++ b/gnovm/tests/files/recursive9b.gno @@ -5,4 +5,4 @@ type Int = func() Int func main() {} // Error: -// main/files/recursive9b.gno:1:1: invalid recursive type: Int -> Int \ No newline at end of file +// main/files/recursive9b.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9c.gno b/gnovm/tests/files/recursive9c.gno index ad8659789200..bf08d406dc26 100644 --- a/gnovm/tests/files/recursive9c.gno +++ b/gnovm/tests/files/recursive9c.gno @@ -5,4 +5,4 @@ type Int = []Int func main() {} // Error: -// main/files/recursive9c.gno:1:1: invalid recursive type: Int -> Int +// main/files/recursive9c.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9d.gno b/gnovm/tests/files/recursive9d.gno index ae7310ede0ff..7ea4c934c65b 100644 --- a/gnovm/tests/files/recursive9d.gno +++ b/gnovm/tests/files/recursive9d.gno @@ -7,4 +7,4 @@ type S = struct { func main() {} // Error: -// main/files/recursive9d.gno:1:1: invalid recursive type: S -> S +// main/files/recursive9d.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/switch13.gno b/gnovm/tests/files/switch13.gno index b2223c852565..f69f09d1037f 100644 --- a/gnovm/tests/files/switch13.gno +++ b/gnovm/tests/files/switch13.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/switch13.gno:0:0: i is not a type +// main/files/switch13.gno:8:0: i is not a type diff --git a/gnovm/tests/files/types/assign_literal11.gno b/gnovm/tests/files/types/assign_literal11.gno index 851fe74593d8..ab916e4c7521 100644 --- a/gnovm/tests/files/types/assign_literal11.gno +++ b/gnovm/tests/files/types/assign_literal11.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/assign_literal11.gno:6:2: cannot assign to (const (3.14 bigdec)) +// main/files/types/assign_literal11.gno:6:2: cannot assign to const Pi diff --git a/gnovm/tests/files/types/assign_literal3.gno b/gnovm/tests/files/types/assign_literal3.gno index e4a4441853db..ce051b0dcbbd 100644 --- a/gnovm/tests/files/types/assign_literal3.gno +++ b/gnovm/tests/files/types/assign_literal3.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/assign_literal3.gno:4:2: cannot assign to (const (true bool)) +// main/files/types/assign_literal3.gno:4:2: cannot assign to uverse true diff --git a/gnovm/tests/files/types/assign_nil.gno b/gnovm/tests/files/types/assign_nil.gno index 8c756da3b605..ecbca26dad0d 100644 --- a/gnovm/tests/files/types/assign_nil.gno +++ b/gnovm/tests/files/types/assign_nil.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/assign_nil.gno:7:2: cannot assign to (const (undefined)) +// main/files/types/assign_nil.gno:7:2: cannot assign to uverse nil diff --git a/gnovm/tests/files/types/assign_nil2.gno b/gnovm/tests/files/types/assign_nil2.gno index fd7d509fcccb..a1559d9de1f9 100644 --- a/gnovm/tests/files/types/assign_nil2.gno +++ b/gnovm/tests/files/types/assign_nil2.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/assign_nil2.gno:7:2: cannot assign to (const (undefined)) +// main/files/types/assign_nil2.gno:7:2: cannot assign to uverse nil diff --git a/gnovm/tests/files/var18.gno b/gnovm/tests/files/var18.gno index f01d3871d39b..475c45f6e38b 100644 --- a/gnovm/tests/files/var18.gno +++ b/gnovm/tests/files/var18.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/var18.gno:4:6: missing init expr for c +// main/files/var18.gno:4:6: missing init expr for c diff --git a/gnovm/tests/files/var19.gno b/gnovm/tests/files/var19.gno index 99d7452f6033..2856d6cd05a1 100644 --- a/gnovm/tests/files/var19.gno +++ b/gnovm/tests/files/var19.gno @@ -1,12 +1,11 @@ package main func main() { - var a, b, c = 1, a+1 - + var a, b, c = 1, a + 1 println(a) println(b) println(c) } // Error: -// main/files/var19.gno:4:6: missing init expr for c +// main/files/var19.gno:4:6: missing init expr for c diff --git a/gnovm/tests/files/var22.gno b/gnovm/tests/files/var22.gno index 3f85f0f156d6..5b21f7aa5bc5 100644 --- a/gnovm/tests/files/var22.gno +++ b/gnovm/tests/files/var22.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/var22.gno:8:6: missing init expr for c +// main/files/var22.gno:8:6: missing init expr for c From 43dd3f33e82c28169f1eedce38a6108167c4e5c3 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 00:28:50 -0400 Subject: [PATCH 14/31] feat(tm2): add sdk/params module (#2920) - [x] port x/params -> sdk/params b930513083e8485981878f9763bd3b49a25c3785 - [x] inject in vmkeeper + add std.SetConfig 602245d2efde7af76fd9846c57a91838b2024f2d - [x] implement in `gnoland` 783a044e7505e7fde074bb7a1560b69107132228 - [x] appchain - [x] rpc query - [x] txtar - [x] implement or add comment where we should use it in the existing codebase - [x] namespace's realm target - [ ] questions - [x] do we want a `std.GetConfig` from the contract part? -> No, it allows unsafe, complex, and implicit patterns. If you want to get a value from another contract, you can either import it or use a registry pattern. This approach preserves type safety and other GNOVM protections. - [ ] do we want to restrict the realms able to call `SetConfig` (only `r/sys`), or maybe set an expensive gas price? - [x] after discussion with jae - [x] Rename Config -> Param for consistency - [x] Remove `interface{}` from the setters and use specific types, including in the tm2 implementation (string, uint64, int64, bool, bytes) - [x] Remove the `.` suffix addition, but ensure that the type is explicitly defined by the user; and remove the table. - [x] Remove the types table from the tm2 implementation Related #1418 Related #1856 --------- Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/params.txtar | 65 +++++++++ gno.land/pkg/gnoland/app.go | 16 ++- gno.land/pkg/sdk/vm/builtins.go | 23 +++ gno.land/pkg/sdk/vm/common_test.go | 4 +- gno.land/pkg/sdk/vm/gas_test.go | 2 +- gno.land/pkg/sdk/vm/keeper.go | 19 ++- gno.land/pkg/sdk/vm/keeper_test.go | 56 +++++++- gnovm/stdlibs/generated.go | 130 +++++++++++++++++ gnovm/stdlibs/std/context.go | 1 + gnovm/stdlibs/std/params.gno | 13 ++ gnovm/stdlibs/std/params.go | 72 ++++++++++ misc/genstd/Makefile | 6 + tm2/pkg/sdk/auth/keeper.go | 12 +- tm2/pkg/sdk/bank/keeper.go | 4 +- tm2/pkg/sdk/params/doc.go | 15 ++ tm2/pkg/sdk/params/handler.go | 79 +++++++++++ tm2/pkg/sdk/params/handler_test.go | 58 ++++++++ tm2/pkg/sdk/params/keeper.go | 157 +++++++++++++++++++++ tm2/pkg/sdk/params/keeper_test.go | 142 +++++++++++++++++++ tm2/pkg/sdk/params/test_common.go | 46 ++++++ tm2/pkg/store/README.md | 12 -- 21 files changed, 901 insertions(+), 31 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/params.txtar create mode 100644 gnovm/stdlibs/std/params.gno create mode 100644 gnovm/stdlibs/std/params.go create mode 100644 misc/genstd/Makefile create mode 100644 tm2/pkg/sdk/params/doc.go create mode 100644 tm2/pkg/sdk/params/handler.go create mode 100644 tm2/pkg/sdk/params/handler_test.go create mode 100644 tm2/pkg/sdk/params/keeper.go create mode 100644 tm2/pkg/sdk/params/keeper_test.go create mode 100644 tm2/pkg/sdk/params/test_common.go diff --git a/gno.land/cmd/gnoland/testdata/params.txtar b/gno.land/cmd/gnoland/testdata/params.txtar new file mode 100644 index 000000000000..30363aa63695 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/params.txtar @@ -0,0 +1,65 @@ +# test for https://github.com/gnolang/gno/pull/2920 + +gnoland start + +# query before adding the package +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: $' + +gnokey maketx addpkg -pkgdir $WORK/setter -pkgpath gno.land/r/sys/setter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 + +# query after adding the package, but before setting values +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: $' + + +# set foo (string) +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetFoo -args foo1 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: "foo1"' + +# override foo +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetFoo -args foo2 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: "foo2"' + + +# set bar (bool) +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBar -args true -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: true' + +# override bar +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBar -args false -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: false' + + +# set baz (bool) +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 1337 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: "1337"' + +# override baz +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 31337 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: "31337"' + +-- setter/setter.gno -- +package setter + +import ( + "std" +) + +func SetFoo(newFoo string) { std.SetParamString("foo.string", newFoo) } +func SetBar(newBar bool) { std.SetParamBool("bar.bool", newBar) } +func SetBaz(newBaz int64) { std.SetParamInt64("baz.int64", newBaz) } diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index ca746dbe386b..e784f2148aa1 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -19,6 +19,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/sdk/params" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -87,12 +88,13 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { // Construct keepers. acctKpr := auth.NewAccountKeeper(mainKey, ProtoGnoAccount) bankKpr := bank.NewBankKeeper(acctKpr) - vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr) + paramsKpr := params.NewParamsKeeper(mainKey, "vm") + vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, paramsKpr) // Set InitChainer icc := cfg.InitChainerConfig icc.baseApp = baseApp - icc.acctKpr, icc.bankKpr, icc.vmKpr = acctKpr, bankKpr, vmk + icc.acctKpr, icc.bankKpr, icc.vmKpr, icc.paramsKpr = acctKpr, bankKpr, vmk, paramsKpr baseApp.SetInitChainer(icc.InitChainer) // Set AnteHandler @@ -147,6 +149,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { // Set a handler Route. baseApp.Router().AddRoute("auth", auth.NewHandler(acctKpr)) baseApp.Router().AddRoute("bank", bank.NewHandler(bankKpr)) + baseApp.Router().AddRoute("params", params.NewHandler(paramsKpr)) baseApp.Router().AddRoute("vm", vm.NewHandler(vmk)) // Load latest version. @@ -224,10 +227,11 @@ type InitChainerConfig struct { // These fields are passed directly by NewAppWithOptions, and should not be // configurable by end-users. - baseApp *sdk.BaseApp - vmKpr vm.VMKeeperI - acctKpr auth.AccountKeeperI - bankKpr bank.BankKeeperI + baseApp *sdk.BaseApp + vmKpr vm.VMKeeperI + acctKpr auth.AccountKeeperI + bankKpr bank.BankKeeperI + paramsKpr params.ParamsKeeperI } // InitChainer is the function that can be used as a [sdk.InitChainer]. diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index d4d6b6032b22..161e459873dd 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -55,3 +55,26 @@ func (bnk *SDKBanker) RemoveCoin(b32addr crypto.Bech32Address, denom string, amo panic(err) } } + +// ---------------------------------------- +// SDKParams + +type SDKParams struct { + vmk *VMKeeper + ctx sdk.Context +} + +func NewSDKParams(vmk *VMKeeper, ctx sdk.Context) *SDKParams { + return &SDKParams{ + vmk: vmk, + ctx: ctx, + } +} + +func (prm *SDKParams) SetString(key, value string) { prm.vmk.prmk.SetString(prm.ctx, key, value) } +func (prm *SDKParams) SetBool(key string, value bool) { prm.vmk.prmk.SetBool(prm.ctx, key, value) } +func (prm *SDKParams) SetInt64(key string, value int64) { prm.vmk.prmk.SetInt64(prm.ctx, key, value) } +func (prm *SDKParams) SetUint64(key string, value uint64) { + prm.vmk.prmk.SetUint64(prm.ctx, key, value) +} +func (prm *SDKParams) SetBytes(key string, value []byte) { prm.vmk.prmk.SetBytes(prm.ctx, key, value) } diff --git a/gno.land/pkg/sdk/vm/common_test.go b/gno.land/pkg/sdk/vm/common_test.go index 66975fba923a..7380d3e0f72c 100644 --- a/gno.land/pkg/sdk/vm/common_test.go +++ b/gno.land/pkg/sdk/vm/common_test.go @@ -11,6 +11,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/sdk" authm "github.com/gnolang/gno/tm2/pkg/sdk/auth" bankm "github.com/gnolang/gno/tm2/pkg/sdk/bank" + paramsm "github.com/gnolang/gno/tm2/pkg/sdk/params" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -47,7 +48,8 @@ func _setupTestEnv(cacheStdlibs bool) testEnv { ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNoopLogger()) acck := authm.NewAccountKeeper(iavlCapKey, std.ProtoBaseAccount) bank := bankm.NewBankKeeper(acck) - vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank) + prmk := paramsm.NewParamsKeeper(iavlCapKey, "params") + vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, prmk) mcw := ms.MultiCacheWrap() vmk.Initialize(log.NewNoopLogger(), mcw) diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 4171b1cdbc30..53809a7f2231 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -74,7 +74,7 @@ func TestAddPkgDeliverTx(t *testing.T) { assert.True(t, res.IsOK()) // NOTE: let's try to keep this bellow 100_000 :) - assert.Equal(t, int64(92825), gasDeliver) + assert.Equal(t, int64(93825), gasDeliver) } // Enough gas for a failed transaction. diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index f069cce37230..ef1705c7ae9e 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -23,6 +23,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/sdk/params" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -59,6 +60,7 @@ type VMKeeper struct { iavlKey store.StoreKey acck auth.AccountKeeper bank bank.BankKeeper + prmk params.ParamsKeeper // cached, the DeliverTx persistent state. gnoStore gno.Store @@ -70,13 +72,14 @@ func NewVMKeeper( iavlKey store.StoreKey, acck auth.AccountKeeper, bank bank.BankKeeper, + prmk params.ParamsKeeper, ) *VMKeeper { - // TODO: create an Options struct to avoid too many constructor parameters vmk := &VMKeeper{ baseKey: baseKey, iavlKey: iavlKey, acck: acck, bank: bank, + prmk: prmk, } return vmk } @@ -222,9 +225,15 @@ func (vm *VMKeeper) getGnoTransactionStore(ctx sdk.Context) gno.TransactionStore // Namespace can be either a user or crypto address. var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) +const ( + sysUsersPkgParamKey = "vm/gno.land/r/sys/params.string" + sysUsersPkgDefault = "gno.land/r/sys/users" +) + // checkNamespacePermission check if the user as given has correct permssion to on the given pkg path func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Address, pkgPath string) error { - const sysUsersPkg = "gno.land/r/sys/users" + sysUsersPkg := sysUsersPkgDefault + vm.prmk.GetString(ctx, sysUsersPkgParamKey, &sysUsersPkg) store := vm.getGnoTransactionStore(ctx) @@ -258,6 +267,7 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add OrigPkgAddr: pkgAddr.Bech32(), // XXX: should we remove the banker ? Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } @@ -358,6 +368,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } // Parse and run the files, construct *PV. @@ -458,6 +469,7 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } // Construct machine and evaluate. @@ -556,6 +568,7 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } // Parse and run the files, construct *PV. @@ -715,6 +728,7 @@ func (vm *VMKeeper) QueryEval(ctx sdk.Context, pkgPath string, expr string) (res // OrigSendSpent: nil, OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded. + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } m := gno.NewMachineWithOptions( @@ -781,6 +795,7 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string // OrigSendSpent: nil, OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded. + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } m := gno.NewMachineWithOptions( diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index f6c6b87419d2..c6d8e3f5fa07 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -298,6 +298,60 @@ func Echo(msg string) string { assert.Error(t, err) } +// Using x/params from a realm. +func TestVMKeeperParams(t *testing.T) { + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + + // Give "addr1" some gnots. + addr := crypto.AddressFromPreimage([]byte("addr1")) + acc := env.acck.NewAccountWithAddress(ctx, addr) + env.acck.SetAccount(ctx, acc) + env.bank.SetCoins(ctx, addr, std.MustParseCoins(coinsString)) + // env.prmk. + assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) + + // Create test package. + files := []*std.MemFile{ + {"init.gno", ` +package test + +import "std" + +func init() { + std.SetParamString("foo.string", "foo1") +} + +func Do() string { + std.SetParamInt64("bar.int64", int64(1337)) + std.SetParamString("foo.string", "foo2") // override init + + return "XXX" // return std.GetConfig("gno.land/r/test.foo"), if we want to expose std.GetConfig, maybe as a std.TestGetConfig +}`}, + } + pkgPath := "gno.land/r/test" + msg1 := NewMsgAddPackage(addr, pkgPath, files) + err := env.vmk.AddPackage(ctx, msg1) + assert.NoError(t, err) + + // Run Echo function. + coins := std.MustParseCoins(ugnot.ValueString(9_000_000)) + msg2 := NewMsgCall(addr, coins, pkgPath, "Do", []string{}) + + res, err := env.vmk.Call(ctx, msg2) + assert.NoError(t, err) + _ = res + expected := fmt.Sprintf("(\"%s\" string)\n\n", "XXX") // XXX: return something more useful + assert.Equal(t, expected, res) + + var foo string + var bar int64 + env.vmk.prmk.GetString(ctx, "gno.land/r/test.foo.string", &foo) + env.vmk.prmk.GetInt64(ctx, "gno.land/r/test.bar.int64", &bar) + assert.Equal(t, "foo2", foo) + assert.Equal(t, int64(1337), bar) +} + // Assign admin as OrigCaller on deploying the package. func TestVMKeeperOrigCallerInit(t *testing.T) { env := setupTestEnv() @@ -320,7 +374,7 @@ import "std" var admin std.Address func init() { - admin = std.GetOrigCaller() + admin = std.GetOrigCaller() } func Echo(msg string) string { diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index 7693e9d6e709..b0788fc6d1ba 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -720,6 +720,136 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "std", + "setParamString", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 string + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setParamString( + m, + p0, p1) + }, + }, + { + "std", + "setParamBool", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("bool")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 bool + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setParamBool( + m, + p0, p1) + }, + }, + { + "std", + "setParamInt64", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("int64")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 int64 + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setParamInt64( + m, + p0, p1) + }, + }, + { + "std", + "setParamUint64", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("uint64")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 uint64 + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setParamUint64( + m, + p0, p1) + }, + }, + { + "std", + "setParamBytes", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("[]byte")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 []byte + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setParamBytes( + m, + p0, p1) + }, + }, { "testing", "unixNano", diff --git a/gnovm/stdlibs/std/context.go b/gnovm/stdlibs/std/context.go index ff5c91a14ebc..a0dafe5dc444 100644 --- a/gnovm/stdlibs/std/context.go +++ b/gnovm/stdlibs/std/context.go @@ -18,6 +18,7 @@ type ExecContext struct { OrigSend std.Coins OrigSendSpent *std.Coins // mutable Banker BankerInterface + Params ParamsInterface EventLogger *sdk.EventLogger } diff --git a/gnovm/stdlibs/std/params.gno b/gnovm/stdlibs/std/params.gno new file mode 100644 index 000000000000..ce400270cdac --- /dev/null +++ b/gnovm/stdlibs/std/params.gno @@ -0,0 +1,13 @@ +package std + +func setParamString(key string, val string) +func setParamBool(key string, val bool) +func setParamInt64(key string, val int64) +func setParamUint64(key string, val uint64) +func setParamBytes(key string, val []byte) + +func SetParamString(key string, val string) { setParamString(key, val) } +func SetParamBool(key string, val bool) { setParamBool(key, val) } +func SetParamInt64(key string, val int64) { setParamInt64(key, val) } +func SetParamUint64(key string, val uint64) { setParamUint64(key, val) } +func SetParamBytes(key string, val []byte) { setParamBytes(key, val) } diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go new file mode 100644 index 000000000000..e21bd9912dd3 --- /dev/null +++ b/gnovm/stdlibs/std/params.go @@ -0,0 +1,72 @@ +package std + +import ( + "fmt" + "strings" + "unicode" + + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" +) + +// ParamsInterface is the interface through which Gno is capable of accessing +// the blockchain's params. +// +// The name is what it is to avoid a collision with Gno's Params, when +// transpiling. +type ParamsInterface interface { + SetString(key, val string) + SetBool(key string, val bool) + SetInt64(key string, val int64) + SetUint64(key string, val uint64) + SetBytes(key string, val []byte) +} + +func X_setParamString(m *gno.Machine, key, val string) { + pk := pkey(m, key, "string") + GetContext(m).Params.SetString(pk, val) +} + +func X_setParamBool(m *gno.Machine, key string, val bool) { + pk := pkey(m, key, "bool") + GetContext(m).Params.SetBool(pk, val) +} + +func X_setParamInt64(m *gno.Machine, key string, val int64) { + pk := pkey(m, key, "int64") + GetContext(m).Params.SetInt64(pk, val) +} + +func X_setParamUint64(m *gno.Machine, key string, val uint64) { + pk := pkey(m, key, "uint64") + GetContext(m).Params.SetUint64(pk, val) +} + +func X_setParamBytes(m *gno.Machine, key string, val []byte) { + pk := pkey(m, key, "bytes") + GetContext(m).Params.SetBytes(pk, val) +} + +func pkey(m *gno.Machine, key string, kind string) string { + // validate key. + untypedKey := strings.TrimSuffix(key, "."+kind) + if key == untypedKey { + m.Panic(typedString("invalid param key: " + key)) + } + + if len(key) == 0 { + m.Panic(typedString("empty param key")) + } + first := rune(key[0]) + if !unicode.IsLetter(first) && first != '_' { + m.Panic(typedString("invalid param key: " + key)) + } + for _, char := range untypedKey[1:] { + if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '_' { + m.Panic(typedString("invalid param key: " + key)) + } + } + + // decorate key with realm and type. + _, rlmPath := currentRealm(m) + return fmt.Sprintf("%s.%s", rlmPath, key) +} diff --git a/misc/genstd/Makefile b/misc/genstd/Makefile new file mode 100644 index 000000000000..2022a6cc2b44 --- /dev/null +++ b/misc/genstd/Makefile @@ -0,0 +1,6 @@ +run: + cd ../../gnovm/stdlibs && go run ../../misc/genstd + cd ../../gnovm/tests/stdlibs && go run ../../../misc/genstd + +test: + go test -v . diff --git a/tm2/pkg/sdk/auth/keeper.go b/tm2/pkg/sdk/auth/keeper.go index e43b53898448..7669b8ace738 100644 --- a/tm2/pkg/sdk/auth/keeper.go +++ b/tm2/pkg/sdk/auth/keeper.go @@ -31,11 +31,6 @@ func NewAccountKeeper( } } -// Logger returns a module-specific logger. -func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { - return ctx.Logger().With("module", fmt.Sprintf("auth")) -} - // NewAccountWithAddress implements AccountKeeper. func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) std.Account { acc := ak.proto() @@ -53,7 +48,12 @@ func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Addre return acc } -// GetAccount implements AccountKeeper. +// Logger returns a module-specific logger. +func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +// GetAccount returns a specific account in the AccountKeeper. func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr crypto.Address) std.Account { stor := ctx.Store(ak.key) bz := stor.Get(AddressStoreKey(addr)) diff --git a/tm2/pkg/sdk/bank/keeper.go b/tm2/pkg/sdk/bank/keeper.go index 5d3699c99ef2..f98e6b3e225d 100644 --- a/tm2/pkg/sdk/bank/keeper.go +++ b/tm2/pkg/sdk/bank/keeper.go @@ -25,8 +25,8 @@ type BankKeeperI interface { var _ BankKeeperI = BankKeeper{} -// BBankKeeper only allows transfers between accounts without the possibility of -// creating coins. It implements the BankKeeper interface. +// BankKeeper only allows transfers between accounts without the possibility of +// creating coins. It implements the BankKeeperI interface. type BankKeeper struct { ViewKeeper diff --git a/tm2/pkg/sdk/params/doc.go b/tm2/pkg/sdk/params/doc.go new file mode 100644 index 000000000000..a433b5eb115a --- /dev/null +++ b/tm2/pkg/sdk/params/doc.go @@ -0,0 +1,15 @@ +// Package params provides a lightweight implementation inspired by the x/params +// module of the Cosmos SDK. +// +// It includes a keeper for managing key-value pairs with module identifiers as +// prefixes, along with a global querier for retrieving any key from any module. +// +// Changes: This version removes the concepts of subspaces and proposals, +// allowing the creation of multiple keepers identified by a provided prefix. +// Proposals may be added later when governance modules are introduced. The +// transient store and .Modified helper have also been removed but can be +// implemented later if needed. Keys are represented as strings instead of +// []byte. +// +// XXX: removes isAlphaNum validation for keys. +package params diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go new file mode 100644 index 000000000000..b662fc06c589 --- /dev/null +++ b/tm2/pkg/sdk/params/handler.go @@ -0,0 +1,79 @@ +package params + +import ( + "fmt" + "strings" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/std" +) + +type paramsHandler struct { + params ParamsKeeper +} + +func NewHandler(params ParamsKeeper) paramsHandler { + return paramsHandler{ + params: params, + } +} + +func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { + errMsg := fmt.Sprintf("unrecognized params message type: %T", msg) + return abciResult(std.ErrUnknownRequest(errMsg)) +} + +//---------------------------------------- +// Query + +func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + switch secondPart(req.Path) { + case bh.params.prefix: + return bh.queryParam(ctx, req) + default: + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("unknown params query endpoint")) + return + } +} + +// queryParam returns param for a key. +func (bh paramsHandler) queryParam(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + // parse key from path. + key := thirdPartWithSlashes(req.Path) + if key == "" { + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("param key is empty")) + } + + // XXX: validate? + + val := bh.params.GetRaw(ctx, key) + + res.Data = val + return +} + +//---------------------------------------- +// misc + +func abciResult(err error) sdk.Result { + return sdk.ABCIResultFromError(err) +} + +// returns the second component of a path. +func secondPart(path string) string { + parts := strings.SplitN(path, "/", 3) + if len(parts) < 2 { + return "" + } else { + return parts[1] + } +} + +// returns the third component of a path, including other slashes. +func thirdPartWithSlashes(path string) string { + split := strings.SplitN(path, "/", 3) + return split[2] +} diff --git a/tm2/pkg/sdk/params/handler_test.go b/tm2/pkg/sdk/params/handler_test.go new file mode 100644 index 000000000000..1fff5d007d39 --- /dev/null +++ b/tm2/pkg/sdk/params/handler_test.go @@ -0,0 +1,58 @@ +package params + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + tu "github.com/gnolang/gno/tm2/pkg/sdk/testutils" +) + +func TestInvalidMsg(t *testing.T) { + t.Parallel() + + h := NewHandler(ParamsKeeper{}) + res := h.Process(sdk.NewContext(sdk.RunTxModeDeliver, nil, &bft.Header{ChainID: "test-chain"}, nil), tu.NewTestMsg()) + require.False(t, res.IsOK()) + require.True(t, strings.Contains(res.Log, "unrecognized params message type")) +} + +func TestQuery(t *testing.T) { + t.Parallel() + + env := setupTestEnv() + h := NewHandler(env.keeper) + + req := abci.RequestQuery{ + Path: "params/params_test/foo/bar.string", + } + + res := h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Nil(t, res.Data) + + env.keeper.SetString(env.ctx, "foo/bar.string", "baz") + + res = h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Equal(t, string(res.Data), `"baz"`) +} + +func TestQuerierRouteNotFound(t *testing.T) { + t.Parallel() + + env := setupTestEnv() + h := NewHandler(env.keeper) + req := abci.RequestQuery{ + Path: "params/notfound", + Data: []byte{}, + } + res := h.Query(env.ctx, req) + require.Error(t, res.Error) +} diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go new file mode 100644 index 000000000000..ffeb1775acbe --- /dev/null +++ b/tm2/pkg/sdk/params/keeper.go @@ -0,0 +1,157 @@ +package params + +import ( + "log/slog" + "strings" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" +) + +const ( + ModuleName = "params" + StoreKey = ModuleName +) + +type ParamsKeeperI interface { + GetString(ctx sdk.Context, key string, ptr *string) + GetInt64(ctx sdk.Context, key string, ptr *int64) + GetUint64(ctx sdk.Context, key string, ptr *uint64) + GetBool(ctx sdk.Context, key string, ptr *bool) + GetBytes(ctx sdk.Context, key string, ptr *[]byte) + + SetString(ctx sdk.Context, key string, value string) + SetInt64(ctx sdk.Context, key string, value int64) + SetUint64(ctx sdk.Context, key string, value uint64) + SetBool(ctx sdk.Context, key string, value bool) + SetBytes(ctx sdk.Context, key string, value []byte) + + Has(ctx sdk.Context, key string) bool + GetRaw(ctx sdk.Context, key string) []byte + + // XXX: ListKeys? +} + +var _ ParamsKeeperI = ParamsKeeper{} + +// global paramstore Keeper. +type ParamsKeeper struct { + key store.StoreKey + prefix string +} + +// NewParamsKeeper returns a new ParamsKeeper. +func NewParamsKeeper(key store.StoreKey, prefix string) ParamsKeeper { + return ParamsKeeper{ + key: key, + prefix: prefix, + } +} + +// Logger returns a module-specific logger. +// XXX: why do we expose this? +func (pk ParamsKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +func (pk ParamsKeeper) Has(ctx sdk.Context, key string) bool { + stor := ctx.Store(pk.key) + return stor.Has([]byte(key)) +} + +func (pk ParamsKeeper) GetRaw(ctx sdk.Context, key string) []byte { + stor := ctx.Store(pk.key) + return stor.Get([]byte(key)) +} + +func (pk ParamsKeeper) GetString(ctx sdk.Context, key string, ptr *string) { + checkSuffix(key, ".string") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetBool(ctx sdk.Context, key string, ptr *bool) { + checkSuffix(key, ".bool") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetInt64(ctx sdk.Context, key string, ptr *int64) { + checkSuffix(key, ".int64") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetUint64(ctx sdk.Context, key string, ptr *uint64) { + checkSuffix(key, ".uint64") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetBytes(ctx sdk.Context, key string, ptr *[]byte) { + checkSuffix(key, ".bytes") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) SetString(ctx sdk.Context, key, value string) { + checkSuffix(key, ".string") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetBool(ctx sdk.Context, key string, value bool) { + checkSuffix(key, ".bool") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetInt64(ctx sdk.Context, key string, value int64) { + checkSuffix(key, ".int64") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetUint64(ctx sdk.Context, key string, value uint64) { + checkSuffix(key, ".uint64") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetBytes(ctx sdk.Context, key string, value []byte) { + checkSuffix(key, ".bytes") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) getIfExists(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + if bz == nil { + return + } + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) get(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) set(ctx sdk.Context, key string, value interface{}) { + stor := ctx.Store(pk.key) + bz, err := amino.MarshalJSON(value) + if err != nil { + panic(err) + } + stor.Set([]byte(key), bz) +} + +func checkSuffix(key, expectedSuffix string) { + var ( + noSuffix = !strings.HasSuffix(key, expectedSuffix) + noName = len(key) == len(expectedSuffix) + // XXX: additional sanity checks? + ) + if noSuffix || noName { + panic(`key should be like "` + expectedSuffix + `"`) + } +} diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go new file mode 100644 index 000000000000..45a97ae44ad0 --- /dev/null +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -0,0 +1,142 @@ +package params + +import ( + "reflect" + "testing" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/stretchr/testify/require" +) + +func TestKeeper(t *testing.T) { + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + _ = store // XXX: add store tests? + + require.False(t, keeper.Has(ctx, "param1.string")) + require.False(t, keeper.Has(ctx, "param2.bool")) + require.False(t, keeper.Has(ctx, "param3.uint64")) + require.False(t, keeper.Has(ctx, "param4.int64")) + require.False(t, keeper.Has(ctx, "param5.bytes")) + + // initial set + require.NotPanics(t, func() { keeper.SetString(ctx, "param1.string", "foo") }) + require.NotPanics(t, func() { keeper.SetBool(ctx, "param2.bool", true) }) + require.NotPanics(t, func() { keeper.SetUint64(ctx, "param3.uint64", 42) }) + require.NotPanics(t, func() { keeper.SetInt64(ctx, "param4.int64", -1337) }) + require.NotPanics(t, func() { keeper.SetBytes(ctx, "param5.bytes", []byte("hello world!")) }) + + require.True(t, keeper.Has(ctx, "param1.string")) + require.True(t, keeper.Has(ctx, "param2.bool")) + require.True(t, keeper.Has(ctx, "param3.uint64")) + require.True(t, keeper.Has(ctx, "param4.int64")) + require.True(t, keeper.Has(ctx, "param5.bytes")) + + var ( + param1 string + param2 bool + param3 uint64 + param4 int64 + param5 []byte + ) + + require.NotPanics(t, func() { keeper.GetString(ctx, "param1.string", ¶m1) }) + require.NotPanics(t, func() { keeper.GetBool(ctx, "param2.bool", ¶m2) }) + require.NotPanics(t, func() { keeper.GetUint64(ctx, "param3.uint64", ¶m3) }) + require.NotPanics(t, func() { keeper.GetInt64(ctx, "param4.int64", ¶m4) }) + require.NotPanics(t, func() { keeper.GetBytes(ctx, "param5.bytes", ¶m5) }) + + require.Equal(t, param1, "foo") + require.Equal(t, param2, true) + require.Equal(t, param3, uint64(42)) + require.Equal(t, param4, int64(-1337)) + require.Equal(t, param5, []byte("hello world!")) + + // reset + require.NotPanics(t, func() { keeper.SetString(ctx, "param1.string", "bar") }) + require.NotPanics(t, func() { keeper.SetBool(ctx, "param2.bool", false) }) + require.NotPanics(t, func() { keeper.SetUint64(ctx, "param3.uint64", 12345) }) + require.NotPanics(t, func() { keeper.SetInt64(ctx, "param4.int64", 1000) }) + require.NotPanics(t, func() { keeper.SetBytes(ctx, "param5.bytes", []byte("bye")) }) + + require.True(t, keeper.Has(ctx, "param1.string")) + require.True(t, keeper.Has(ctx, "param2.bool")) + require.True(t, keeper.Has(ctx, "param3.uint64")) + require.True(t, keeper.Has(ctx, "param4.int64")) + require.True(t, keeper.Has(ctx, "param5.bytes")) + + require.NotPanics(t, func() { keeper.GetString(ctx, "param1.string", ¶m1) }) + require.NotPanics(t, func() { keeper.GetBool(ctx, "param2.bool", ¶m2) }) + require.NotPanics(t, func() { keeper.GetUint64(ctx, "param3.uint64", ¶m3) }) + require.NotPanics(t, func() { keeper.GetInt64(ctx, "param4.int64", ¶m4) }) + require.NotPanics(t, func() { keeper.GetBytes(ctx, "param5.bytes", ¶m5) }) + + require.Equal(t, param1, "bar") + require.Equal(t, param2, false) + require.Equal(t, param3, uint64(12345)) + require.Equal(t, param4, int64(1000)) + require.Equal(t, param5, []byte("bye")) + + // invalid sets + require.PanicsWithValue(t, `key should be like ".string"`, func() { keeper.SetString(ctx, "invalid.int64", "hello") }) + require.PanicsWithValue(t, `key should be like ".int64"`, func() { keeper.SetInt64(ctx, "invalid.string", int64(42)) }) + require.PanicsWithValue(t, `key should be like ".uint64"`, func() { keeper.SetUint64(ctx, "invalid.int64", uint64(42)) }) + require.PanicsWithValue(t, `key should be like ".bool"`, func() { keeper.SetBool(ctx, "invalid.int64", true) }) + require.PanicsWithValue(t, `key should be like ".bytes"`, func() { keeper.SetBytes(ctx, "invalid.int64", []byte("hello")) }) +} + +// adapted from TestKeeperSubspace from Cosmos SDK, but adapted to a subspace-less Keeper. +func TestKeeper_internal(t *testing.T) { + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + + kvs := []struct { + key string + param interface{} + zero interface{} + ptr interface{} + }{ + {"string", "test", "", new(string)}, + {"bool", true, false, new(bool)}, + {"int16", int16(1), int16(0), new(int16)}, + {"int32", int32(1), int32(0), new(int32)}, + {"int64", int64(1), int64(0), new(int64)}, + {"uint16", uint16(1), uint16(0), new(uint16)}, + {"uint32", uint32(1), uint32(0), new(uint32)}, + {"uint64", uint64(1), uint64(0), new(uint64)}, + {"struct", s{1}, s{0}, new(s)}, + } + + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) + } + + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.getIfExists(ctx, "invalid", kv.ptr) }, "keeper.GetIfExists panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "keeper.GetIfExists unmarshalls when no value exists, tc #%d", i) + require.Panics(t, func() { keeper.get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value exists, tc #%d", i) + + require.NotPanics(t, func() { keeper.getIfExists(ctx, kv.key, kv.ptr) }, "keeper.GetIfExists panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + require.NotPanics(t, func() { keeper.get(ctx, kv.key, kv.ptr) }, "keeper.Get panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + + require.Panics(t, func() { keeper.get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value existt, tc #%d", i) + + require.Panics(t, func() { keeper.get(ctx, kv.key, nil) }, "invalid keeper.Get not panics when the pointer is nil, tc #%d", i) + } + + for i, kv := range kvs { + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) + err := amino.UnmarshalJSON(bz, kv.ptr) + require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + } +} + +type s struct{ I int } + +func indirect(ptr interface{}) interface{} { return reflect.ValueOf(ptr).Elem().Interface() } diff --git a/tm2/pkg/sdk/params/test_common.go b/tm2/pkg/sdk/params/test_common.go new file mode 100644 index 000000000000..8243ee867de8 --- /dev/null +++ b/tm2/pkg/sdk/params/test_common.go @@ -0,0 +1,46 @@ +package params + +import ( + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/db/memdb" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" + "github.com/gnolang/gno/tm2/pkg/store/iavl" +) + +type testEnv struct { + ctx sdk.Context + store store.Store + keeper ParamsKeeper +} + +func setupTestEnv() testEnv { + db := memdb.NewMemDB() + paramsCapKey := store.NewStoreKey("paramsCapKey") + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(paramsCapKey, iavl.StoreConstructor, db) + ms.LoadLatestVersion() + + prefix := "params_test" + keeper := NewParamsKeeper(paramsCapKey, prefix) + + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{Height: 1, ChainID: "test-chain-id"}, log.NewNoopLogger()) + // XXX: context key? + ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxTxBytes: 1024, + MaxDataBytes: 1024 * 100, + MaxBlockBytes: 1024 * 100, + MaxGas: 10 * 1000 * 1000, + TimeIotaMS: 10, + }, + Validator: &abci.ValidatorParams{ + PubKeyTypeURLs: []string{}, // XXX + }, + }) + + stor := ctx.Store(paramsCapKey) + return testEnv{ctx: ctx, store: stor, keeper: keeper} +} diff --git a/tm2/pkg/store/README.md b/tm2/pkg/store/README.md index abf5c26bc07f..24ae0c805acd 100644 --- a/tm2/pkg/store/README.md +++ b/tm2/pkg/store/README.md @@ -116,15 +116,3 @@ type traceOperation struct { ``` `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`. - -## Transient - -`transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. - -```go -type Store struct { - dbadapter.Store -} -``` - -`Store.Store` is a `dbadapter.Store` with a `memdb.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected. From e34a8f7eb14fb5d255a810ea9ae89d860a790598 Mon Sep 17 00:00:00 2001 From: SunSpirit <48086732+sunspirit99@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:48:35 +0700 Subject: [PATCH 15/31] fix(tm2): enable coin benchmark tests after fixing panic error (#2884) Relate to https://github.com/gnolang/gno/issues/907 Make a few small fixes to get this test working
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
    --- tm2/pkg/std/coin_benchmark_test.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tm2/pkg/std/coin_benchmark_test.go b/tm2/pkg/std/coin_benchmark_test.go index 2d4d2f038903..3cb056123733 100644 --- a/tm2/pkg/std/coin_benchmark_test.go +++ b/tm2/pkg/std/coin_benchmark_test.go @@ -2,12 +2,10 @@ package std import ( "fmt" - "strconv" "testing" ) func BenchmarkCoinsAdditionIntersect(b *testing.B) { - b.Skip("TODO: panicking benchmark") benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { b.Helper() @@ -15,11 +13,16 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) coinsB := Coins(make([]Coin, numCoinsB)) + maxCoins := max(numCoinsA, numCoinsB) + denomLength := len(fmt.Sprint(maxCoins)) + for i := 0; i < numCoinsA; i++ { - coinsA[i] = NewCoin("COINZ_"+strconv.Itoa(i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsA[i] = NewCoin(denom, int64(i+1)) } for i := 0; i < numCoinsB; i++ { - coinsB[i] = NewCoin("COINZ_"+strconv.Itoa(i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsB[i] = NewCoin(denom, int64(i+1)) } b.ResetTimer() @@ -39,7 +42,6 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { } func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { - b.Skip("TODO: panicking benchmark") benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { b.Helper() @@ -47,11 +49,16 @@ func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) coinsB := Coins(make([]Coin, numCoinsB)) + maxCoins := max(numCoinsA, numCoinsB) + denomLength := len(fmt.Sprint(maxCoins)) + for i := 0; i < numCoinsA; i++ { - coinsA[i] = NewCoin("COINZ_"+strconv.Itoa(numCoinsB+i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsA[i] = NewCoin(denom, int64(i+1)) } for i := 0; i < numCoinsB; i++ { - coinsB[i] = NewCoin("COINZ_"+strconv.Itoa(i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsB[i] = NewCoin(denom, int64(i+1)) } b.ResetTimer() From 247f2c63b54d75cf9033abb2f1f3c10344f78991 Mon Sep 17 00:00:00 2001 From: Miguel Victoria Villaquiran Date: Wed, 23 Oct 2024 16:29:25 +0200 Subject: [PATCH 16/31] feat(ghverify): emit event when user request verification (#2778) related to #2777
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
    Co-authored-by: 6h057 <15034695+omarsy@users.noreply.github.com> --- examples/gno.land/r/gnoland/ghverify/contract.gno | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/gno.land/r/gnoland/ghverify/contract.gno b/examples/gno.land/r/gnoland/ghverify/contract.gno index 4f2715b79e7a..3b8f7fcbbe10 100644 --- a/examples/gno.land/r/gnoland/ghverify/contract.gno +++ b/examples/gno.land/r/gnoland/ghverify/contract.gno @@ -83,6 +83,11 @@ func RequestVerification(githubHandle string) { ); err != nil { panic(err) } + std.Emit( + "verification_requested", + "from", gnoAddress, + "handle", githubHandle, + ) } // GnorkleEntrypoint is the entrypoint to the gnorkle oracle handler. From 5e7183784e385ce3817bf4e19f7a15a8f277e75e Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 24 Oct 2024 00:41:05 +0900 Subject: [PATCH 17/31] test(p/uint256): Increase Test Coverage for `uint256` Package (#2931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Screenshot 2024-10-10 at 2 53 28 PM Increased the test coverage of the `p/demo/uint256` package. Previously, only about 40% was covered, but now it has increased to 90% (checked in go). The existing implementation of the uint256 function is unmodified except for modifying it to use the strconv package. - [X] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [X] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). --------- Co-authored-by: Morgan --- .../p/demo/uint256/arithmetic_test.gno | 384 ++++++++++-------- .../gno.land/p/demo/uint256/bitwise_test.gno | 187 ++++++--- examples/gno.land/p/demo/uint256/cmp_test.gno | 200 ++++++--- .../p/demo/uint256/conversion_test.gno | 139 ++++++- examples/gno.land/p/demo/uint256/uint256.gno | 5 +- .../gno.land/p/demo/uint256/uint256_test.gno | 127 ++++++ examples/gno.land/p/demo/uint256/utils.gno | 160 -------- 7 files changed, 760 insertions(+), 442 deletions(-) create mode 100644 examples/gno.land/p/demo/uint256/uint256_test.gno diff --git a/examples/gno.land/p/demo/uint256/arithmetic_test.gno b/examples/gno.land/p/demo/uint256/arithmetic_test.gno index 9f45a5077541..079d89fa7947 100644 --- a/examples/gno.land/p/demo/uint256/arithmetic_test.gno +++ b/examples/gno.land/p/demo/uint256/arithmetic_test.gno @@ -1,6 +1,8 @@ package uint256 -import "testing" +import ( + "testing" +) type binOp2Test struct { x, y, want string @@ -16,30 +18,45 @@ func TestAdd(t *testing.T) { {"18446744073709551615", "18446744073709551615", "36893488147419103230"}, // uint64 overflow } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + want := MustFromDecimal(tt.want) + got := new(Uint).Add(x, y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Add(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} - got := &Uint{} - got.Add(x, y) +func TestAddOverflow(t *testing.T) { + tests := []struct { + x, y string + want string + overflow bool + }{ + {"0", "1", "1", false}, + {"1", "0", "1", false}, + {"1", "1", "2", false}, + {"10", "10", "20", false}, + {"18446744073709551615", "18446744073709551615", "36893488147419103230", false}, // uint64 overflow, but not Uint256 overflow + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "1", "0", true}, // 2^256 - 1 + 1, should overflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819967", "57896044618658097711785492504343953926634992332820282019728792003956564819968", "115792089237316195423570985008687907853269984665640564039457584007913129639935", false}, // (2^255 - 1) + 2^255, no overflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819967", "57896044618658097711785492504343953926634992332820282019728792003956564819969", "0", true}, // (2^255 - 1) + (2^255 + 1), should overflow + } - if got.Neq(want) { - t.Errorf("Add(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want, _ := FromDecimal(tt.want) + + got, overflow := new(Uint).AddOverflow(x, y) + + if got.Cmp(want) != 0 || overflow != tt.overflow { + t.Errorf("AddOverflow(%s, %s) = (%s, %v), want (%s, %v)", + tt.x, tt.y, got.ToString(), overflow, tt.want, tt.overflow) } } } @@ -50,33 +67,53 @@ func TestSub(t *testing.T) { {"1", "1", "0"}, {"10", "10", "0"}, {"31337", "1337", "30000"}, - {"2", "3", "115792089237316195423570985008687907853269984665640564039457584007913129639935"}, // underflow + {"2", "3", twoPow256Sub1}, // underflow } for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + x := MustFromDecimal(tc.x) + y := MustFromDecimal(tc.y) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + want := MustFromDecimal(tc.want) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + got := new(Uint).Sub(x, y) + + if got.Neq(want) { + t.Errorf( + "Sub(%s, %s) = %v, want %v", + tc.x, tc.y, got.ToString(), want.ToString(), + ) } + } +} - got := &Uint{} - got.Sub(x, y) +func TestSubOverflow(t *testing.T) { + tests := []struct { + x, y string + want string + overflow bool + }{ + {"1", "0", "1", false}, + {"1", "1", "0", false}, + {"10", "10", "0", false}, + {"31337", "1337", "30000", false}, + {"0", "1", "115792089237316195423570985008687907853269984665640564039457584007913129639935", true}, // 0 - 1, should underflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819968", "1", "57896044618658097711785492504343953926634992332820282019728792003956564819967", false}, // 2^255 - 1, no underflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819968", "57896044618658097711785492504343953926634992332820282019728792003956564819969", "115792089237316195423570985008687907853269984665640564039457584007913129639935", true}, // 2^255 - (2^255 + 1), should underflow + } - if got.Neq(want) { - t.Errorf("Sub(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + for _, tc := range tests { + x := MustFromDecimal(tc.x) + y := MustFromDecimal(tc.y) + want := MustFromDecimal(tc.want) + + got, overflow := new(Uint).SubOverflow(x, y) + + if got.Cmp(want) != 0 || overflow != tc.overflow { + t.Errorf( + "SubOverflow(%s, %s) = (%s, %v), want (%s, %v)", + tc.x, tc.y, got.ToString(), overflow, tc.want, tc.overflow, + ) } } } @@ -89,30 +126,50 @@ func TestMul(t *testing.T) { {"18446744073709551615", "2", "36893488147419103230"}, // uint64 overflow } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) + got := new(Uint).Mul(x, y) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Mul(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } +func TestMulOverflow(t *testing.T) { + tests := []struct { + x string + y string + wantZ string + wantOver bool + }{ + {"0x1", "0x1", "0x1", false}, + {"0x0", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x0", false}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", true}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1", true}, + {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x2", "0x0", true}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", false}, + {"0x100000000000000000", "0x100000000000000000", "0x10000000000000000000000000000000000", false}, + {"0x10000000000000000000000000000000", "0x10000000000000000000000000000000", "0x100000000000000000000000000000000000000000000000000000000000000", false}, + } - got := &Uint{} - got.Mul(x, y) + for _, tt := range tests { + x := MustFromHex(tt.x) + y := MustFromHex(tt.y) + wantZ := MustFromHex(tt.wantZ) - if got.Neq(want) { - t.Errorf("Mul(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + gotZ, gotOver := new(Uint).MulOverflow(x, y) + + if gotZ.Neq(wantZ) { + t.Errorf( + "MulOverflow(%s, %s) = %s, want %s", + tt.x, tt.y, gotZ.ToString(), wantZ.ToString(), + ) + } + if gotOver != tt.wantOver { + t.Errorf("MulOverflow(%s, %s) = %v, want %v", tt.x, tt.y, gotOver, tt.wantOver) } } } @@ -123,32 +180,19 @@ func TestDiv(t *testing.T) { {"31337", "0", "0"}, {"0", "31337", "0"}, {"1", "1", "1"}, + {"1000000000000000000", "3", "333333333333333333"}, + {twoPow256Sub1, "2", "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } - - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) - got := &Uint{} - got.Div(x, y) + got := new(Uint).Div(x, y) if got.Neq(want) { - t.Errorf("Div(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + t.Errorf("Div(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } } } @@ -160,32 +204,56 @@ func TestMod(t *testing.T) { {"0", "31337", "0"}, {"2", "31337", "2"}, {"1", "1", "0"}, + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "2", "1"}, // 2^256 - 1 mod 2 + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "3", "0"}, // 2^256 - 1 mod 3 + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "57896044618658097711785492504343953926634992332820282019728792003956564819968", "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, // 2^256 - 1 mod 2^255 } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + got := new(Uint).Mod(x, y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Mod(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} - got := &Uint{} - got.Mod(x, y) +func TestMulMod(t *testing.T) { + tests := []struct { + x string + y string + m string + want string + }{ + {"0x1", "0x1", "0x2", "0x1"}, + {"0x10", "0x10", "0x7", "0x4"}, + {"0x100", "0x100", "0x17", "0x9"}, + {"0x31337", "0x31337", "0x31338", "0x1"}, + {"0x0", "0x31337", "0x31338", "0x0"}, + {"0x31337", "0x0", "0x31338", "0x0"}, + {"0x2", "0x3", "0x5", "0x1"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x0"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0x1"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0x0"}, + } + + for _, tt := range tests { + x := MustFromHex(tt.x) + y := MustFromHex(tt.y) + m := MustFromHex(tt.m) + want := MustFromHex(tt.want) + + got := new(Uint).MulMod(x, y, m) if got.Neq(want) { - t.Errorf("Mod(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + t.Errorf( + "MulMod(%s, %s, %s) = %s, want %s", + tt.x, tt.y, tt.m, got.ToString(), want.ToString(), + ) } } } @@ -206,30 +274,11 @@ func TestDivMod(t *testing.T) { {"2", "31337", "0", "2"}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } - - wantDiv, err := FromDecimal(tc.wantDiv) - if err != nil { - t.Error(err) - continue - } - - wantMod, err := FromDecimal(tc.wantMod) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + wantDiv := MustFromDecimal(tt.wantDiv) + wantMod := MustFromDecimal(tt.wantMod) gotDiv := new(Uint) gotMod := new(Uint) @@ -237,13 +286,13 @@ func TestDivMod(t *testing.T) { for i := range gotDiv.arr { if gotDiv.arr[i] != wantDiv.arr[i] { - t.Errorf("DivMod(%s, %s) got Div %v, want Div %v", tc.x, tc.y, gotDiv, wantDiv) + t.Errorf("DivMod(%s, %s) got Div %v, want Div %v", tt.x, tt.y, gotDiv, wantDiv) break } } for i := range gotMod.arr { if gotMod.arr[i] != wantMod.arr[i] { - t.Errorf("DivMod(%s, %s) got Mod %v, want Mod %v", tc.x, tc.y, gotMod, wantMod) + t.Errorf("DivMod(%s, %s) got Mod %v, want Mod %v", tt.x, tt.y, gotMod, wantMod) break } } @@ -259,27 +308,17 @@ func TestNeg(t *testing.T) { {"115792089237316195423570985008687907853269984665640564039457584007913129608599", "31337"}, {"0", "0"}, {"2", "115792089237316195423570985008687907853269984665640564039457584007913129639934"}, - {"1", "115792089237316195423570985008687907853269984665640564039457584007913129639935"}, + {"1", twoPow256Sub1}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + want := MustFromDecimal(tt.want) - got := &Uint{} - got.Neg(x) + got := new(Uint).Neg(x) if got.Neq(want) { - t.Errorf("Neg(%s) = %v, want %v", tc.x, got.ToString(), want.ToString()) + t.Errorf("Neg(%s) = %v, want %v", tt.x, got.ToString(), want.ToString()) } } } @@ -297,30 +336,57 @@ func TestExp(t *testing.T) { {"2", "256", "0"}, // overflow } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + got := new(Uint).Exp(x, y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf( + "Exp(%s, %s) = %v, want %v", + tt.x, tt.y, got.ToString(), want.ToString(), + ) } + } +} + +func TestExp_LargeExponent(t *testing.T) { + tests := []struct { + name string + base string + exponent string + expected string + }{ + { + name: "2^129", + base: "2", + exponent: "680564733841876926926749214863536422912", + expected: "0", + }, + { + name: "2^193", + base: "2", + exponent: "12379400392853802746563808384000000000000000000", + expected: "0", + }, + } - got := &Uint{} - got.Exp(x, y) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + base := MustFromDecimal(tt.base) + exponent := MustFromDecimal(tt.exponent) + expected := MustFromDecimal(tt.expected) - if got.Neq(want) { - t.Errorf("Exp(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) - } + result := new(Uint).Exp(base, exponent) + + if result.Neq(expected) { + t.Errorf( + "Test %s failed. Expected %s, got %s", + tt.name, expected.ToString(), result.ToString(), + ) + } + }) } } diff --git a/examples/gno.land/p/demo/uint256/bitwise_test.gno b/examples/gno.land/p/demo/uint256/bitwise_test.gno index aba89edfabf6..3561629fd941 100644 --- a/examples/gno.land/p/demo/uint256/bitwise_test.gno +++ b/examples/gno.land/p/demo/uint256/bitwise_test.gno @@ -37,11 +37,14 @@ func TestOr(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).Or(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("Or(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).Or(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "Or(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -93,11 +96,14 @@ func TestAnd(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).And(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("And(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).And(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "And(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -126,11 +132,14 @@ func TestNot(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).Not(&tc.x) - if *res != tc.want { - t.Errorf("Not(%s) = %s, want %s", tc.x.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).Not(&tt.x) + if *res != tt.want { + t.Errorf( + "Not(%s) = %s, want %s", + tt.x.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -182,11 +191,14 @@ func TestAndNot(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).AndNot(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("AndNot(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).AndNot(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "AndNot(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -238,11 +250,14 @@ func TestXor(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).Xor(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("Xor(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).Xor(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "Xor(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -272,26 +287,31 @@ func TestLsh(t *testing.T) { {"31337", 193, "393411074163624830192644266310117284962799025126338899061243904"}, {"31337", 255, "57896044618658097711785492504343953926634992332820282019728792003956564819968"}, {"31337", 256, "0"}, - } + // 64 < n < 128 + {"1", 65, "36893488147419103232"}, + {"31337", 100, "39724366859352024754702188346867712"}, - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + // 128 < n < 192 + {"1", 129, "680564733841876926926749214863536422912"}, + {"31337", 150, "44725660946326664792723507424638829088826130956288"}, - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } + // 192 < n < 256 + {"1", 193, "12554203470773361527671578846415332832204710888928069025792"}, + {"31337", 200, "50356617492943978264658466087695012475238275216171379079839219712"}, - got := &Uint{} - got.Lsh(x, tc.y) + // n > 256 + {"1", 257, "0"}, + {"31337", 300, "0"}, + } + + for _, tt := range tests { + x := MustFromDecimal(tt.x) + want := MustFromDecimal(tt.want) + + got := new(Uint).Lsh(x, tt.y) if got.Neq(want) { - t.Errorf("Lsh(%s, %d) = %s, want %s", tc.x, tc.y, got.ToString(), want.ToString()) + t.Errorf("Lsh(%s, %d) = %s, want %s", tt.x, tt.y, got.ToString(), want.ToString()) } } } @@ -319,26 +339,85 @@ func TestRsh(t *testing.T) { {"196705537081812415096322133155058642481399512563169449530621952", 192, "31337"}, {"10663428532201448629551770073089320442396672", 128, "31337"}, {"578065619037836218990592", 64, "31337"}, + {twoPow256Sub1, 256, "0"}, + // outliers + {"340282366920938463463374607431768211455", 129, "0"}, + {"18446744073709551615", 65, "0"}, + {twoPow256Sub1, 1, "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, + + // n > 256 + {"1", 257, "0"}, + {"31337", 300, "0"}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + + want := MustFromDecimal(tt.want) + got := new(Uint).Rsh(x, tt.y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Rsh(%s, %d) = %s, want %s", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} + +func TestSRsh(t *testing.T) { + tests := []struct { + x string + y uint + want string + }{ + // Positive numbers (behaves like Rsh) + {"0x0", 0, "0x0"}, + {"0x0", 1, "0x0"}, + {"0x1", 0, "0x1"}, + {"0x1", 1, "0x0"}, + {"0x31337", 0, "0x31337"}, + {"0x31337", 4, "0x3133"}, + {"0x31337", 8, "0x313"}, + {"0x31337", 16, "0x3"}, + {"0x10000000000000000", 64, "0x1"}, // 2^64 >> 64 - got := &Uint{} - got.Rsh(x, tc.y) + // // Numbers with MSB set (negative numbers in two's complement) + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 4, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 64, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 128, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 192, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 255, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - if got.Neq(want) { - t.Errorf("Rsh(%s, %d) = %s, want %s", tc.x, tc.y, got.ToString(), want.ToString()) + // Large positive number close to max value + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1, "0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 2, "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 64, "0x7fffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 128, "0x7fffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 192, "0x7fffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 255, "0x0"}, + + // Specific cases + {"0x8000000000000000000000000000000000000000000000000000000000000000", 1, "0xc000000000000000000000000000000000000000000000000000000000000000"}, + {"0x8000000000000000000000000000000000000000000000000000000000000001", 1, "0xc000000000000000000000000000000000000000000000000000000000000000"}, + + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 65, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 127, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 129, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 193, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + + // n > 256 + {"0x1", 257, "0x0"}, + {"0x31337", 300, "0x0"}, + } + + for _, tt := range tests { + x := MustFromHex(tt.x) + want := MustFromHex(tt.want) + + got := new(Uint).SRsh(x, tt.y) + + if !got.Eq(want) { + t.Errorf("SRsh(%s, %d) = %s, want %s", tt.x, tt.y, got.ToString(), want.ToString()) } } } diff --git a/examples/gno.land/p/demo/uint256/cmp_test.gno b/examples/gno.land/p/demo/uint256/cmp_test.gno index 930079f70f00..51c9e70d9a73 100644 --- a/examples/gno.land/p/demo/uint256/cmp_test.gno +++ b/examples/gno.land/p/demo/uint256/cmp_test.gno @@ -5,6 +5,39 @@ import ( "testing" ) +func TestSign(t *testing.T) { + tests := []struct { + input *Uint + expected int + }{ + { + input: NewUint(0), + expected: 0, + }, + { + input: NewUint(1), + expected: 1, + }, + { + input: NewUint(0x7fffffffffffffff), + expected: 1, + }, + { + input: NewUint(0x8000000000000000), + expected: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.input.ToString(), func(t *testing.T) { + result := tt.input.Sign() + if result != tt.expected { + t.Errorf("Sign() = %d; want %d", result, tt.expected) + } + }) + } +} + func TestCmp(t *testing.T) { tests := []struct { x, y string @@ -20,17 +53,8 @@ func TestCmp(t *testing.T) { } for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + x := MustFromDecimal(tc.x) + y := MustFromDecimal(tc.y) got := x.Cmp(y) if got != tc.want { @@ -49,16 +73,12 @@ func TestIsZero(t *testing.T) { {"10", false}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) got := x.IsZero() - if got != tc.want { - t.Errorf("IsZero(%s) = %v, want %v", tc.x, got, tc.want) + if got != tt.want { + t.Errorf("IsZero(%s) = %v, want %v", tt.x, got, tt.want) } } } @@ -77,31 +97,53 @@ func TestLtUint64(t *testing.T) { } for _, tc := range tests { - var x *Uint - var err error - - if strings.HasPrefix(tc.x, "0x") { - x, err = FromHex(tc.x) - if err != nil { - t.Error(err) - continue - } - } else { - x, err = FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - } + x := parseTestString(t, tc.x) got := x.LtUint64(tc.y) - if got != tc.want { t.Errorf("LtUint64(%s, %d) = %v, want %v", tc.x, tc.y, got, tc.want) } } } +func TestUint_GtUint64(t *testing.T) { + tests := []struct { + name string + z string + n uint64 + want bool + }{ + { + name: "z > n", + z: "1", + n: 0, + want: true, + }, + { + name: "z < n", + z: "18446744073709551615", + n: 0xFFFFFFFFFFFFFFFF, + want: false, + }, + { + name: "z == n", + z: "18446744073709551615", + n: 0xFFFFFFFFFFFFFFFF, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + z := MustFromDecimal(tt.z) + + if got := z.GtUint64(tt.n); got != tt.want { + t.Errorf("Uint.GtUint64() = %v, want %v", got, tt.want) + } + }) + } +} + func TestSGT(t *testing.T) { x := MustFromHex("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe") y := MustFromHex("0x0") @@ -127,37 +169,83 @@ func TestEq(t *testing.T) { {"0xffffffffffffffff", "18446744073709551615", true}, {"0x10000000000000000", "18446744073709551616", true}, {"0", "0", true}, - {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "115792089237316195423570985008687907853269984665640564039457584007913129639935", true}, + {twoPow256Sub1, twoPow256Sub1, true}, } - for i, tc := range tests { - var x *Uint - var err error + for _, tt := range tests { + x := parseTestString(t, tt.x) - if strings.HasPrefix(tc.x, "0x") { - x, err = FromHex(tc.x) - if err != nil { - t.Error(err) - continue - } - } else { - x, err = FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + y, err := FromDecimal(tt.y) + if err != nil { + t.Error(err) + continue } - y, err := FromDecimal(tc.y) + got := x.Eq(y) + + if got != tt.want { + t.Errorf("Eq(%s, %s) = %v, want %v", tt.x, tt.y, got, tt.want) + } + } +} + +func TestUint_Lte(t *testing.T) { + tests := []struct { + z, x string + want bool + }{ + {"10", "20", true}, + {"20", "10", false}, + {"10", "10", true}, + {"0", "0", true}, + } + + for _, tt := range tests { + z, err := FromDecimal(tt.z) if err != nil { t.Error(err) continue } + x, err := FromDecimal(tt.x) + if err != nil { + t.Error(err) + continue + } + if got := z.Lte(x); got != tt.want { + t.Errorf("Uint.Lte(%v, %v) = %v, want %v", tt.z, tt.x, got, tt.want) + } + } +} - got := x.Eq(y) +func TestUint_Gte(t *testing.T) { + tests := []struct { + z, x string + want bool + }{ + {"20", "10", true}, + {"10", "20", false}, + {"10", "10", true}, + {"0", "0", true}, + } - if got != tc.want { - t.Errorf("Eq(%s, %s) = %v, want %v", tc.x, tc.y, got, tc.want) + for _, tt := range tests { + z := parseTestString(t, tt.z) + x := parseTestString(t, tt.x) + + if got := z.Gte(x); got != tt.want { + t.Errorf("Uint.Gte(%v, %v) = %v, want %v", tt.z, tt.x, got, tt.want) } } } + +func parseTestString(_ *testing.T, s string) *Uint { + var x *Uint + + if strings.HasPrefix(s, "0x") { + x = MustFromHex(s) + } else { + x = MustFromDecimal(s) + } + + return x +} diff --git a/examples/gno.land/p/demo/uint256/conversion_test.gno b/examples/gno.land/p/demo/uint256/conversion_test.gno index ee3aad0f819d..0ea20158be4d 100644 --- a/examples/gno.land/p/demo/uint256/conversion_test.gno +++ b/examples/gno.land/p/demo/uint256/conversion_test.gno @@ -14,18 +14,18 @@ func TestIsUint64(t *testing.T) { {"0x10000000000000000", false}, } - for _, tc := range tests { - x := MustFromHex(tc.x) + for _, tt := range tests { + x := MustFromHex(tt.x) got := x.IsUint64() - if got != tc.want { - t.Errorf("IsUint64(%s) = %v, want %v", tc.x, got, tc.want) + if got != tt.want { + t.Errorf("IsUint64(%s) = %v, want %v", tt.x, got, tt.want) } } } func TestDec(t *testing.T) { - testCases := []struct { + tests := []struct { name string z Uint want string @@ -43,16 +43,133 @@ func TestDec(t *testing.T) { { name: "max possible value", z: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}}, - want: "115792089237316195423570985008687907853269984665640564039457584007913129639935", + want: twoPow256Sub1, }, } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - result := tc.z.Dec() - if result != tc.want { - t.Errorf("Dec(%v) = %s, want %s", tc.z, result, tc.want) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.z.Dec() + if result != tt.want { + t.Errorf("Dec(%v) = %s, want %s", tt.z, result, tt.want) } }) } } + +func TestUint_Scan(t *testing.T) { + tests := []struct { + name string + input interface{} + want *Uint + wantErr bool + }{ + { + name: "nil", + input: nil, + want: NewUint(0), + }, + { + name: "valid scientific notation", + input: "1e4", + want: NewUint(10000), + }, + { + name: "valid decimal string", + input: "12345", + want: NewUint(12345), + }, + { + name: "valid byte slice", + input: []byte("12345"), + want: NewUint(12345), + }, + { + name: "invalid string", + input: "invalid", + wantErr: true, + }, + { + name: "out of range", + input: "115792089237316195423570985008687907853269984665640564039457584007913129639936", // 2^256 + wantErr: true, + }, + { + name: "unsupported type", + input: 123, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + z := new(Uint) + err := z.Scan(tt.input) + + if tt.wantErr { + if err == nil { + t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr) + } + } else { + if err != nil { + t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr) + } + if !z.Eq(tt.want) { + t.Errorf("Scan() = %v, want %v", z, tt.want) + } + } + }) + } +} + +func TestSetBytes(t *testing.T) { + tests := []struct { + input []byte + expected string + }{ + {[]byte{}, "0"}, + {[]byte{0x01}, "1"}, + {[]byte{0x12, 0x34}, "4660"}, + {[]byte{0x12, 0x34, 0x56}, "1193046"}, + {[]byte{0x12, 0x34, 0x56, 0x78}, "305419896"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a}, "78187493530"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "20015998343868"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "5124095576030430"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "1311768467463790320"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}, "335812727670730321938"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}, "85968058283706962416180"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56}, "22007822920628982378542166"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78}, "5634002667681019488906794616"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a}, "1442304682926340989160139421850"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "369229998829143293224995691993788"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "94522879700260683065598897150409950"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "24197857203266734864793317670504947440"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}, "6194651444036284125387089323649266544658"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}, "1585830769673288736099094866854212235432500"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56}, "405972677036361916441368285914678332270720086"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78}, "103929005321308650608990281194157653061304342136"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a}, "26605825362255014555901511985704359183693911586970"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "6811091292737283726310787068340315951025641366264508"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "1743639370940744633935561489495120883462564189763714270"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "446371678960830626287503741310750946166416432579510853360"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}, "114271149813972640329600957775552242218602606740354778460178"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}, "29253414352376995924377845190541374007962267325530823285805620"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56}, "7488874074208510956640728368778591746038340435335890761166238806"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78}, "1917151762997378804900026462407319486985815151445988034858557134456"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a}, "490790851327328974054406774376273788668368678770172936923790626420890"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "125642457939796217357928134240326089899102381765164271852490400363748028"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "32164469232587831643629602365523479014170209731882053594237542493119495390"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "8234104123542484900769178205574010627627573691361805720124810878238590820080"}, + // over 32 bytes (last 32 bytes are used) + {append([]byte{0xff}, []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}...), "8234104123542484900769178205574010627627573691361805720124810878238590820080"}, + } + + for _, test := range tests { + z := new(Uint) + z.SetBytes(test.input) + expected := MustFromDecimal(test.expected) + if z.Cmp(expected) != 0 { + t.Errorf("SetBytes(%x) = %s, expected %s", test.input, z.ToString(), test.expected) + } + } +} diff --git a/examples/gno.land/p/demo/uint256/uint256.gno b/examples/gno.land/p/demo/uint256/uint256.gno index 80da0ba882bb..3d183362992e 100644 --- a/examples/gno.land/p/demo/uint256/uint256.gno +++ b/examples/gno.land/p/demo/uint256/uint256.gno @@ -5,6 +5,7 @@ package uint256 import ( "errors" "math/bits" + "strconv" ) const ( @@ -143,10 +144,10 @@ func (z *Uint) fromDecimal(bs string) error { if remaining <= 0 { return nil // Done } else if remaining > 19 { - num, err = parseUint(bs[remaining-19:remaining], 10, 64) + num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64) } else { // Final round - num, err = parseUint(bs, 10, 64) + num, err = strconv.ParseUint(bs, 10, 64) } if err != nil { return err diff --git a/examples/gno.land/p/demo/uint256/uint256_test.gno b/examples/gno.land/p/demo/uint256/uint256_test.gno new file mode 100644 index 000000000000..0089af15c665 --- /dev/null +++ b/examples/gno.land/p/demo/uint256/uint256_test.gno @@ -0,0 +1,127 @@ +package uint256 + +import ( + "testing" +) + +func TestSetAllOne(t *testing.T) { + z := Zero() + z.SetAllOne() + if z.ToString() != twoPow256Sub1 { + t.Errorf("Expected all ones, got %s", z.ToString()) + } +} + +func TestByte(t *testing.T) { + tests := []struct { + input string + position uint64 + expected byte + }{ + {"0x1000000000000000000000000000000000000000000000000000000000000000", 0, 16}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0, 255}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 255}, + } + + for i, tt := range tests { + z, _ := FromHex(tt.input) + n := NewUint(tt.position) + result := z.Byte(n) + + if result.arr[0] != uint64(tt.expected) { + t.Errorf("Test case %d failed. Input: %s, Position: %d, Expected: %d, Got: %d", + i, tt.input, tt.position, tt.expected, result.arr[0]) + } + + // check other array elements are 0 + if result.arr[1] != 0 || result.arr[2] != 0 || result.arr[3] != 0 { + t.Errorf("Test case %d failed. Non-zero values in upper bytes", i) + } + } + + // overflow + z, _ := FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + n := NewUint(32) + result := z.Byte(n) + + if !result.IsZero() { + t.Errorf("Expected zero for position >= 32, got %v", result) + } +} + +func TestBitLen(t *testing.T) { + tests := []struct { + input string + expected int + }{ + {"0x0", 0}, + {"0x1", 1}, + {"0xff", 8}, + {"0x100", 9}, + {"0xffff", 16}, + {"0x10000", 17}, + {"0xffffffffffffffff", 64}, + {"0x10000000000000000", 65}, + {"0xffffffffffffffffffffffffffffffff", 128}, + {"0x100000000000000000000000000000000", 129}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 256}, + } + + for i, tt := range tests { + z, _ := FromHex(tt.input) + result := z.BitLen() + + if result != tt.expected { + t.Errorf("Test case %d failed. Input: %s, Expected: %d, Got: %d", + i, tt.input, tt.expected, result) + } + } +} + +func TestByteLen(t *testing.T) { + tests := []struct { + input string + expected int + }{ + {"0x0", 0}, + {"0x1", 1}, + {"0xff", 1}, + {"0x100", 2}, + {"0xffff", 2}, + {"0x10000", 3}, + {"0xffffffffffffffff", 8}, + {"0x10000000000000000", 9}, + {"0xffffffffffffffffffffffffffffffff", 16}, + {"0x100000000000000000000000000000000", 17}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32}, + } + + for i, tt := range tests { + z, _ := FromHex(tt.input) + result := z.ByteLen() + + if result != tt.expected { + t.Errorf("Test case %d failed. Input: %s, Expected: %d, Got: %d", + i, tt.input, tt.expected, result) + } + } +} + +func TestClone(t *testing.T) { + tests := []struct { + input string + expected string + }{ + {"0x1", "1"}, + {"0x100", "256"}, + {"0x10000000000000000", "18446744073709551616"}, + } + + for _, tt := range tests { + z, _ := FromHex(tt.input) + result := z.Clone() + if result.ToString() != tt.expected { + t.Errorf("Test %s failed. Expected %s, got %s", tt.input, tt.expected, result.ToString()) + } + } +} diff --git a/examples/gno.land/p/demo/uint256/utils.gno b/examples/gno.land/p/demo/uint256/utils.gno index 969728f33699..bcc7bb283e01 100644 --- a/examples/gno.land/p/demo/uint256/utils.gno +++ b/examples/gno.land/p/demo/uint256/utils.gno @@ -1,63 +1,5 @@ package uint256 -// lower(c) is a lower-case letter if and only if -// c is either that lower-case letter or the equivalent upper-case letter. -// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'. -// Note that lower of non-letters can produce other non-letters. -func lower(c byte) byte { - return c | ('x' - 'X') -} - -// underscoreOK reports whether the underscores in s are allowed. -// Checking them in this one function lets all the parsers skip over them simply. -// Underscore must appear only between digits or between a base prefix and a digit. -func underscoreOK(s string) bool { - // saw tracks the last character (class) we saw: - // ^ for beginning of number, - // 0 for a digit or base prefix, - // _ for an underscore, - // ! for none of the above. - saw := '^' - i := 0 - - // Optional sign. - if len(s) >= 1 && (s[0] == '-' || s[0] == '+') { - s = s[1:] - } - - // Optional base prefix. - hex := false - if len(s) >= 2 && s[0] == '0' && (lower(s[1]) == 'b' || lower(s[1]) == 'o' || lower(s[1]) == 'x') { - i = 2 - saw = '0' // base prefix counts as a digit for "underscore as digit separator" - hex = lower(s[1]) == 'x' - } - - // Number proper. - for ; i < len(s); i++ { - // Digits are always okay. - if '0' <= s[i] && s[i] <= '9' || hex && 'a' <= lower(s[i]) && lower(s[i]) <= 'f' { - saw = '0' - continue - } - // Underscore must follow digit. - if s[i] == '_' { - if saw != '0' { - return false - } - saw = '_' - continue - } - // Underscore must also be followed by digit. - if saw == '_' { - return false - } - // Saw non-digit, non-underscore. - saw = '!' - } - return saw != '_' -} - func checkNumberS(input string) error { const fn = "UnmarshalText" l := len(input) @@ -76,105 +18,3 @@ func checkNumberS(input string) error { } return nil } - -// ParseUint is like ParseUint but for unsigned numbers. -// -// A sign prefix is not permitted. -func parseUint(s string, base int, bitSize int) (uint64, error) { - const fnParseUint = "ParseUint" - - if s == "" { - return 0, errSyntax(fnParseUint, s) - } - - base0 := base == 0 - - s0 := s - switch { - case 2 <= base && base <= 36: - // valid base; nothing to do - - case base == 0: - // Look for octal, hex prefix. - base = 10 - if s[0] == '0' { - switch { - case len(s) >= 3 && lower(s[1]) == 'b': - base = 2 - s = s[2:] - case len(s) >= 3 && lower(s[1]) == 'o': - base = 8 - s = s[2:] - case len(s) >= 3 && lower(s[1]) == 'x': - base = 16 - s = s[2:] - default: - base = 8 - s = s[1:] - } - } - - default: - return 0, errInvalidBase(fnParseUint, base) - } - - if bitSize == 0 { - bitSize = uintSize - } else if bitSize < 0 || bitSize > 64 { - return 0, errInvalidBitSize(fnParseUint, bitSize) - } - - // Cutoff is the smallest number such that cutoff*base > maxUint64. - // Use compile-time constants for common cases. - var cutoff uint64 - switch base { - case 10: - cutoff = MaxUint64/10 + 1 - case 16: - cutoff = MaxUint64/16 + 1 - default: - cutoff = MaxUint64/uint64(base) + 1 - } - - maxVal := uint64(1)<= byte(base) { - return 0, errSyntax(fnParseUint, s0) - } - - if n >= cutoff { - // n*base overflows - return maxVal, errRange(fnParseUint, s0) - } - n *= uint64(base) - - n1 := n + uint64(d) - if n1 < n || n1 > maxVal { - // n+d overflows - return maxVal, errRange(fnParseUint, s0) - } - n = n1 - } - - if underscores && !underscoreOK(s0) { - return 0, errSyntax(fnParseUint, s0) - } - - return n, nil -} From d9617858b3bf9fa94961e0d556cca516cc962414 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Thu, 24 Oct 2024 01:42:43 +0900 Subject: [PATCH 18/31] test(stdlibs/io): add additional test (#2898) # Description Fixed a failing test in the io package. Additionally, I activated some previously commented-out tests by bypassing the need for `os.CreateTemp` using `bytes.Buffer`.
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
    --------- Co-authored-by: Morgan Bazalgette --- gnovm/stdlibs/io/export_test.gno | 12 -- gnovm/stdlibs/io/io_test.gno | 208 ++++++++++++++++++++----------- gnovm/stdlibs/io/multi_test.gno | 61 +++++---- 3 files changed, 167 insertions(+), 114 deletions(-) delete mode 100644 gnovm/stdlibs/io/export_test.gno diff --git a/gnovm/stdlibs/io/export_test.gno b/gnovm/stdlibs/io/export_test.gno deleted file mode 100644 index 6204ffc4591b..000000000000 --- a/gnovm/stdlibs/io/export_test.gno +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package io - -// exported for test -var ( - ErrInvalidWrite = errInvalidWrite - ErrWhence = errWhence - ErrOffset = errOffset -) diff --git a/gnovm/stdlibs/io/io_test.gno b/gnovm/stdlibs/io/io_test.gno index a7533a87799f..4915982057b5 100644 --- a/gnovm/stdlibs/io/io_test.gno +++ b/gnovm/stdlibs/io/io_test.gno @@ -1,4 +1,4 @@ -package io_test +package io // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -8,7 +8,6 @@ import ( "bytes" "errors" "fmt" - "io" "strings" "testing" ) @@ -16,8 +15,8 @@ import ( // A version of bytes.Buffer without ReadFrom and WriteTo type Buffer struct { bytes.Buffer - io.ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom. - io.WriterTo // conflicts with and hides bytes.Buffer's WriterTo. + ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom. + WriterTo // conflicts with and hides bytes.Buffer's WriterTo. } // Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy, CopyBuffer and CopyN. @@ -26,7 +25,7 @@ func TestCopy(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } @@ -36,12 +35,12 @@ func TestCopyNegative(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello") - io.Copy(wb, &io.LimitedReader{R: rb, N: -1}) + Copy(wb, &LimitedReader{R: rb, N: -1}) if wb.String() != "" { t.Errorf("Copy on LimitedReader with N<0 copied data") } - io.CopyN(wb, rb, -1) + CopyN(wb, rb, -1) if wb.String() != "" { t.Errorf("CopyN with N<0 copied data") } @@ -51,7 +50,7 @@ func TestCopyBuffer(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyBuffer(wb, rb, make([]byte, 1)) // Tiny buffer to keep it honest. + CopyBuffer(wb, rb, make([]byte, 1)) // Tiny buffer to keep it honest. if wb.String() != "hello, world." { t.Errorf("CopyBuffer did not work properly") } @@ -61,7 +60,7 @@ func TestCopyBufferNil(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyBuffer(wb, rb, nil) // Should allocate a buffer. + CopyBuffer(wb, rb, nil) // Should allocate a buffer. if wb.String() != "hello, world." { t.Errorf("CopyBuffer did not work properly") } @@ -71,7 +70,7 @@ func TestCopyReadFrom(t *testing.T) { rb := new(Buffer) wb := new(bytes.Buffer) // implements ReadFrom. rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } @@ -81,7 +80,7 @@ func TestCopyWriteTo(t *testing.T) { rb := new(bytes.Buffer) // implements WriteTo. wb := new(Buffer) rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } @@ -93,7 +92,7 @@ type writeToChecker struct { writeToCalled bool } -func (wt *writeToChecker) WriteTo(w io.Writer) (int64, error) { +func (wt *writeToChecker) WriteTo(w Writer) (int64, error) { wt.writeToCalled = true return wt.Buffer.WriteTo(w) } @@ -105,7 +104,7 @@ func TestCopyPriority(t *testing.T) { rb := new(writeToChecker) wb := new(bytes.Buffer) rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } else if !rb.writeToCalled { @@ -135,7 +134,7 @@ func (w errWriter) Write([]byte) (int, error) { func TestCopyReadErrWriteErr(t *testing.T) { er, ew := errors.New("readError"), errors.New("writeError") r, w := zeroErrReader{err: er}, errWriter{err: ew} - n, err := io.Copy(w, r) + n, err := Copy(w, r) if n != 0 || err != ew { t.Errorf("Copy(zeroErrReader, errWriter) = %d, %v; want 0, writeError", n, err) } @@ -145,7 +144,7 @@ func TestCopyN(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyN(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { t.Errorf("CopyN did not work properly") } @@ -155,7 +154,7 @@ func TestCopyNReadFrom(t *testing.T) { rb := new(Buffer) wb := new(bytes.Buffer) // implements ReadFrom. rb.WriteString("hello") - io.CopyN(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { t.Errorf("CopyN did not work properly") } @@ -165,7 +164,7 @@ func TestCopyNWriteTo(t *testing.T) { rb := new(bytes.Buffer) // implements WriteTo. wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyN(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { t.Errorf("CopyN did not work properly") } @@ -178,7 +177,7 @@ func BenchmarkCopyNSmall(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - io.CopyN(buf, rd, 512) + CopyN(buf, rd, 512) rd.Reset(bs) } } @@ -190,13 +189,13 @@ func BenchmarkCopyNLarge(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - io.CopyN(buf, rd, 32*1024) + CopyN(buf, rd, 32*1024) rd.Reset(bs) } } type noReadFrom struct { - w io.Writer + w Writer } func (w *noReadFrom) Write(p []byte) (n int, err error) { @@ -215,32 +214,32 @@ func TestCopyNEOF(t *testing.T) { b := new(bytes.Buffer) - n, err := io.CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) + n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) if n != 3 || err != nil { t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err) } - n, err = io.CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) - if n != 3 || err != io.EOF { + n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) + if n != 3 || err != EOF { t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err) } - n, err = io.CopyN(b, strings.NewReader("foo"), 3) // b has read from + n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from if n != 3 || err != nil { t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err) } - n, err = io.CopyN(b, strings.NewReader("foo"), 4) // b has read from - if n != 3 || err != io.EOF { + n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from + if n != 3 || err != EOF { t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err) } - n, err = io.CopyN(b, wantedAndErrReader{}, 5) + n, err = CopyN(b, wantedAndErrReader{}, 5) if n != 5 || err != nil { t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) } - n, err = io.CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5) + n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5) if n != 5 || err != nil { t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) } @@ -268,7 +267,7 @@ func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) { func TestReadAtLeastWithDataAndEOF(t *testing.T) { var rb dataAndErrorBuffer - rb.err = io.EOF + rb.err = EOF testReadAtLeast(t, &rb) } @@ -278,41 +277,41 @@ func TestReadAtLeastWithDataAndError(t *testing.T) { testReadAtLeast(t, &rb) } -func testReadAtLeast(t *testing.T, rb io.ReadWriter) { +func testReadAtLeast(t *testing.T, rb ReadWriter) { rb.Write([]byte("0123")) buf := make([]byte, 2) - n, err := io.ReadAtLeast(rb, buf, 2) + n, err := ReadAtLeast(rb, buf, 2) if err != nil { t.Error(err) } if n != 2 { t.Errorf("expected to have read 2 bytes, got %v", n) } - n, err = io.ReadAtLeast(rb, buf, 4) - if err != io.ErrShortBuffer { - t.Errorf("expected ErrShortBuffer got %v", err) + n, err = ReadAtLeast(rb, buf, 4) + if err != ErrShortBuffer { + t.Errorf("expected `ErrShortBuffer` got %v", err) } if n != 0 { t.Errorf("expected to have read 0 bytes, got %v", n) } - n, err = io.ReadAtLeast(rb, buf, 1) + n, err = ReadAtLeast(rb, buf, 1) if err != nil { t.Error(err) } if n != 2 { t.Errorf("expected to have read 2 bytes, got %v", n) } - n, err = io.ReadAtLeast(rb, buf, 2) - if err != io.EOF { + n, err = ReadAtLeast(rb, buf, 2) + if err != EOF { t.Errorf("expected EOF, got %v", err) } if n != 0 { t.Errorf("expected to have read 0 bytes, got %v", n) } rb.Write([]byte("4")) - n, err = io.ReadAtLeast(rb, buf, 2) - want := io.ErrUnexpectedEOF - if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != io.EOF { + n, err = ReadAtLeast(rb, buf, 2) + want := ErrUnexpectedEOF + if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF { want = rb.err } if err != want { @@ -323,14 +322,14 @@ func testReadAtLeast(t *testing.T, rb io.ReadWriter) { } } -/* XXX no io.Pipe() no chan +/* XXX no Pipe() no chan func TestTeeReader(t *testing.T) { src := []byte("hello, world") dst := make([]byte, len(src)) rb := bytes.NewBuffer(src) wb := new(bytes.Buffer) - r := io.TeeReader(rb, wb) - if n, err := io.ReadFull(r, dst); err != nil || n != len(src) { + r := TeeReader(rb, wb) + if n, err := ReadFull(r, dst); err != nil || n != len(src) { t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src)) } if !bytes.Equal(dst, src) { @@ -339,14 +338,14 @@ func TestTeeReader(t *testing.T) { if !bytes.Equal(wb.Bytes(), src) { t.Errorf("bytes written = %q want %q", wb.Bytes(), src) } - if n, err := r.Read(dst); n != 0 || err != io.EOF { + if n, err := r.Read(dst); n != 0 || err != EOF { t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err) } rb = bytes.NewBuffer(src) - pr, pw := io.Pipe() + pr, pw := Pipe() pr.Close() - r = io.TeeReader(rb, pw) - if n, err := io.ReadFull(r, dst); n != 0 || err != io.ErrClosedPipe { + r = TeeReader(rb, pw) + if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe { t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err) } } @@ -363,22 +362,22 @@ func TestSectionReader_ReadAt(t *testing.T) { exp string err error }{ - {data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: io.EOF}, + {data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF}, {data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil}, - {data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: io.EOF}, + {data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF}, {data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil}, {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil}, {data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil}, {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil}, {data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil}, {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil}, - {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: io.EOF}, - {data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: io.EOF}, - {data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: io.EOF}, + {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF}, + {data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF}, + {data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF}, } for i, tt := range tests { r := strings.NewReader(tt.data) - s := io.NewSectionReader(r, int64(tt.off), int64(tt.n)) + s := NewSectionReader(r, int64(tt.off), int64(tt.n)) buf := make([]byte, tt.bufLen) if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err { t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err) @@ -389,9 +388,9 @@ func TestSectionReader_ReadAt(t *testing.T) { func TestSectionReader_Seek(t *testing.T) { // Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader) br := bytes.NewReader([]byte("foo")) - sr := io.NewSectionReader(br, 0, int64(len("foo"))) + sr := NewSectionReader(br, 0, int64(len("foo"))) - for _, whence := range []int{io.SeekStart, io.SeekCurrent, io.SeekEnd} { + for _, whence := range []int{SeekStart, SeekCurrent, SeekEnd} { for offset := int64(-3); offset <= 4; offset++ { brOff, brErr := br.Seek(offset, whence) srOff, srErr := sr.Seek(offset, whence) @@ -403,13 +402,13 @@ func TestSectionReader_Seek(t *testing.T) { } // And verify we can just seek past the end and get an EOF - got, err := sr.Seek(100, io.SeekStart) + got, err := sr.Seek(100, SeekStart) if err != nil || got != 100 { t.Errorf("Seek = %v, %v; want 100, nil", got, err) } n, err := sr.Read(make([]byte, 10)) - if n != 0 || err != io.EOF { + if n != 0 || err != EOF { t.Errorf("Read = %v, %v; want 0, EOF", n, err) } } @@ -425,7 +424,7 @@ func TestSectionReader_Size(t *testing.T) { for _, tt := range tests { r := strings.NewReader(tt.data) - sr := io.NewSectionReader(r, 0, int64(len(tt.data))) + sr := NewSectionReader(r, 0, int64(len(tt.data))) if got := sr.Size(); got != tt.want { t.Errorf("Size = %v; want %v", got, tt.want) } @@ -443,11 +442,11 @@ func (w largeWriter) Write(p []byte) (int, error) { } func TestCopyLargeWriter(t *testing.T) { - want := io.ErrInvalidWrite + want := errInvalidWrite rb := new(Buffer) wb := largeWriter{} rb.WriteString("hello, world.") - if _, err := io.Copy(wb, rb); err != want { + if _, err := Copy(wb, rb); err != want { t.Errorf("Copy error: got %v, want %v", err, want) } @@ -455,7 +454,7 @@ func TestCopyLargeWriter(t *testing.T) { rb = new(Buffer) wb = largeWriter{err: want} rb.WriteString("hello, world.") - if _, err := io.Copy(wb, rb); err != want { + if _, err := Copy(wb, rb); err != want { t.Errorf("Copy error: got %v, want %v", err, want) } } @@ -463,18 +462,18 @@ func TestCopyLargeWriter(t *testing.T) { func TestNopCloserWriterToForwarding(t *testing.T) { for _, tc := range [...]struct { Name string - r io.Reader + r Reader }{ - {"not a WriterTo", io.Reader(nil)}, + {"not a WriterTo", Reader(nil)}, {"a WriterTo", struct { - io.Reader - io.WriterTo + Reader + WriterTo }{}}, } { - nc := io.NopCloser(tc.r) + nc := NopCloser(tc.r) - _, expected := tc.r.(io.WriterTo) - _, got := nc.(io.WriterTo) + _, expected := tc.r.(WriterTo) + _, got := nc.(WriterTo) if expected != got { t.Errorf("NopCloser incorrectly forwards WriterTo for %s, got %t want %t", tc.Name, got, expected) } @@ -496,9 +495,9 @@ func TestNopCloserWriterToForwarding(t *testing.T) { // for _, whence := range []int{-3, -2, -1, 3, 4, 5} { // var offset int64 = 0 // gotOff, gotErr := w.Seek(offset, whence) -// if gotOff != 0 || gotErr != ErrWhence { +// if gotOff != 0 || gotErr != errWhence { // t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", -// whence, offset, gotOff, gotErr, 0, ErrWhence) +// whence, offset, gotOff, gotErr, 0, errWhence) // } // } // }) @@ -508,7 +507,7 @@ func TestNopCloserWriterToForwarding(t *testing.T) { // for _, whence := range []int{SeekStart, SeekCurrent} { // for offset := int64(-3); offset < 0; offset++ { // gotOff, gotErr := w.Seek(offset, whence) -// if gotOff != 0 || gotErr != ErrOffset { +// if gotOff != 0 || gotErr != errOffset { // t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", // whence, offset, gotOff, gotErr, 0, ErrOffset) // } @@ -540,3 +539,70 @@ func TestNopCloserWriterToForwarding(t *testing.T) { // } // }) // } + +// TODO: The original test uses `os.CreateTemp`, but here +// to work around it by using `bytes.Buffer`. +// When `os.CreateTemp` is available in the future, we should change the test +// to use the original approach instead of this method. (just un-comment the test above) +func TestOffsetWriter_Seek(t *testing.T) { + buf := new(bytes.Buffer) + w := NewOffsetWriter(testWriterAt{buf}, 0) + + // Should throw error errWhence if whence is not valid + t.Run("errWhence", func(t *testing.T) { + for _, whence := range []int{-3, -2, -1, 3, 4, 5} { + var offset int64 = 0 + gotOff, gotErr := w.Seek(offset, whence) + if gotOff != 0 || gotErr != errWhence { + t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", + whence, offset, gotOff, gotErr, 0, errWhence) + } + } + }) + + // Should throw error errOffset if offset is negative + t.Run("errOffset", func(t *testing.T) { + for _, whence := range []int{SeekStart, SeekCurrent} { + for offset := int64(-3); offset < 0; offset++ { + gotOff, gotErr := w.Seek(offset, whence) + if gotOff != 0 || gotErr != errOffset { + t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", + whence, offset, gotOff, gotErr, 0, errOffset) + } + } + } + }) + + t.Run("normal", func(t *testing.T) { + tests := []struct { + offset int64 + whence int + returnOff int64 + }{ + {whence: SeekStart, offset: 1, returnOff: 1}, + {whence: SeekStart, offset: 2, returnOff: 2}, + {whence: SeekStart, offset: 3, returnOff: 3}, + {whence: SeekCurrent, offset: 1, returnOff: 4}, + {whence: SeekCurrent, offset: 2, returnOff: 6}, + {whence: SeekCurrent, offset: 3, returnOff: 9}, + } + for idx, tt := range tests { + gotOff, gotErr := w.Seek(tt.offset, tt.whence) + if gotOff != tt.returnOff || gotErr != nil { + t.Errorf("%d:: For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, )", + idx+1, tt.whence, tt.offset, gotOff, gotErr, tt.returnOff) + } + } + }) +} + +type testWriterAt struct { + buf *bytes.Buffer +} + +func (w testWriterAt) WriteAt(p []byte, off int64) (n int, err error) { + if int64(w.buf.Len()) < off+int64(len(p)) { + w.buf.Grow(int(off + int64(len(p)) - int64(w.buf.Len()))) + } + return copy(w.buf.Bytes()[off:], p), nil +} diff --git a/gnovm/stdlibs/io/multi_test.gno b/gnovm/stdlibs/io/multi_test.gno index 313452793189..8932ace2e594 100644 --- a/gnovm/stdlibs/io/multi_test.gno +++ b/gnovm/stdlibs/io/multi_test.gno @@ -1,4 +1,4 @@ -package io_test +package io // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -8,7 +8,6 @@ import ( "bytes" "crypto/sha1" "fmt" - "io" "strings" "testing" ) @@ -18,14 +17,14 @@ type Stringer interface { } func TestMultiReader(t *testing.T) { - var mr io.Reader + var mr Reader var buf []byte nread := 0 withFooBar := func(tests func()) { r1 := strings.NewReader("foo ") r2 := strings.NewReader("") r3 := strings.NewReader("bar") - mr = io.MultiReader(r1, r2, r3) + mr = MultiReader(r1, r2, r3) buf = make([]byte, 20) tests() } @@ -51,13 +50,13 @@ func TestMultiReader(t *testing.T) { expectRead(2, "fo", nil) expectRead(5, "o ", nil) expectRead(5, "bar", nil) - expectRead(5, "", io.EOF) + expectRead(5, "", EOF) }) withFooBar(func() { expectRead(4, "foo ", nil) expectRead(1, "b", nil) expectRead(3, "ar", nil) - expectRead(1, "", io.EOF) + expectRead(1, "", EOF) }) withFooBar(func() { expectRead(5, "foo ", nil) @@ -68,7 +67,7 @@ func TestMultiWriter(t *testing.T) { sink := new(bytes.Buffer) // Hide bytes.Buffer's WriteString method: testMultiWriter(t, struct { - io.Writer + Writer Stringer }{sink, sink}) } @@ -83,11 +82,11 @@ func TestMultiWriter_String(t *testing.T) { func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) { var sink1, sink2 bytes.Buffer type simpleWriter struct { // hide bytes.Buffer's WriteString - io.Writer + Writer } - mw := io.MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2}) + mw := MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2}) allocs := int(testing.AllocsPerRun2(1000, func() { - io.WriteString(mw, "foo") + WriteString(mw, "foo") })) if allocs != 1 { t.Errorf("num allocations = %d; want 1", allocs) @@ -108,24 +107,24 @@ func (c *writeStringChecker) Write(p []byte) (n int, err error) { func TestMultiWriter_StringCheckCall(t *testing.T) { var c writeStringChecker - mw := io.MultiWriter(&c) - io.WriteString(mw, "foo") + mw := MultiWriter(&c) + WriteString(mw, "foo") if !c.called { t.Error("did not see WriteString call to writeStringChecker") } } func testMultiWriter(t *testing.T, sink interface { - io.Writer + Writer Stringer }, ) { sha1 := sha1.New() - mw := io.MultiWriter(sha1, sink) + mw := MultiWriter(sha1, sink) sourceString := "My input text." source := strings.NewReader(sourceString) - written, err := io.Copy(mw, source) + written, err := Copy(mw, source) if written != int64(len(sourceString)) { t.Errorf("short write of %d, not %d", written, len(sourceString)) @@ -183,25 +182,25 @@ func TestMultiWriterSingleChainFlatten(t *testing.T) { func TestMultiWriterError(t *testing.T) { f1 := writerFunc(func(p []byte) (int, error) { - return len(p) / 2, io.ErrShortWrite + return len(p) / 2, ErrShortWrite }) f2 := writerFunc(func(p []byte) (int, error) { t.Errorf("MultiWriter called f2.Write") return len(p), nil }) - w := io.MultiWriter(f1, f2) + w := MultiWriter(f1, f2) n, err := w.Write(make([]byte, 100)) - if n != 50 || err != io.ErrShortWrite { + if n != 50 || err != ErrShortWrite { t.Errorf("Write = %d, %v, want 50, ErrShortWrite", n, err) } } // Test that MultiReader copies the input slice and is insulated from future modification. func TestMultiReaderCopy(t *testing.T) { - slice := []io.Reader{strings.NewReader("hello world")} - r := io.MultiReader(slice...) + slice := []Reader{strings.NewReader("hello world")} + r := MultiReader(slice...) slice[0] = nil - data, err := io.ReadAll(r) + data, err := ReadAll(r) if err != nil || string(data) != "hello world" { t.Errorf("ReadAll() = %q, %v, want %q, nil", data, err, "hello world") } @@ -210,8 +209,8 @@ func TestMultiReaderCopy(t *testing.T) { // Test that MultiWriter copies the input slice and is insulated from future modification. func TestMultiWriterCopy(t *testing.T) { var buf bytes.Buffer - slice := []io.Writer{&buf} - w := io.MultiWriter(slice...) + slice := []Writer{&buf} + w := MultiWriter(slice...) slice[0] = nil n, err := w.Write([]byte("hello world")) if err != nil || n != 11 { @@ -278,12 +277,12 @@ func (b byteAndEOFReader) Read(p []byte) (n int, err error) { panic("unexpected call") } p[0] = byte(b) - return 1, io.EOF + return 1, EOF } // This used to yield bytes forever; issue 16795. func TestMultiReaderSingleByteWithEOF(t *testing.T) { - got, err := io.ReadAll(io.LimitReader(io.MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10)) + got, err := ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10)) if err != nil { t.Fatal(err) } @@ -297,10 +296,10 @@ func TestMultiReaderSingleByteWithEOF(t *testing.T) { // chain continues to return EOF on its final read, rather than // yielding a (0, EOF). func TestMultiReaderFinalEOF(t *testing.T) { - r := io.MultiReader(bytes.NewReader(nil), byteAndEOFReader('a')) + r := MultiReader(bytes.NewReader(nil), byteAndEOFReader('a')) buf := make([]byte, 2) n, err := r.Read(buf) - if n != 1 || err != io.EOF { + if n != 1 || err != EOF { t.Errorf("got %v, %v; want 1, EOF", n, err) } } @@ -343,21 +342,21 @@ func TestInterleavedMultiReader(t *testing.T) { r1 := strings.NewReader("123") r2 := strings.NewReader("45678") - mr1 := io.MultiReader(r1, r2) - mr2 := io.MultiReader(mr1) + mr1 := MultiReader(r1, r2) + mr2 := MultiReader(mr1) buf := make([]byte, 4) // Have mr2 use mr1's []Readers. // Consume r1 (and clear it for GC to handle) and consume part of r2. - n, err := io.ReadFull(mr2, buf) + n, err := ReadFull(mr2, buf) if got := string(buf[:n]); got != "1234" || err != nil { t.Errorf(`ReadFull(mr2) = (%q, %v), want ("1234", nil)`, got, err) } // Consume the rest of r2 via mr1. // This should not panic even though mr2 cleared r1. - n, err = io.ReadFull(mr1, buf) + n, err = ReadFull(mr1, buf) if got := string(buf[:n]); got != "5678" || err != nil { t.Errorf(`ReadFull(mr1) = (%q, %v), want ("5678", nil)`, got, err) } From f4c4204c183cd234f3eefa284da1e19110ba712c Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:55:31 -0400 Subject: [PATCH 19/31] feat(gnovm): add 'gno test -print-events' + cleanup machine between tests (#2975) - [x] add `gno test -print-events` flag for unit tests. Props to @r3v4s for his work on #2071 - [x] add `// Events:` support in `_filetests.gno`. - [x] cleanup `gno.Machine` between unit tests (\o/) . Fixes #1982 Closes #2071 Addresses #2007 --------- Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .github/workflows/examples.yml | 2 +- .../gno.land/p/demo/ownable/ownable_test.gno | 9 --- .../gno.land/r/demo/event/z1_filetest.gno | 11 ++++ examples/gno.land/r/gnoland/events/events.gno | 9 +-- .../gno.land/r/gnoland/events/events_test.gno | 13 ++-- gnovm/cmd/gno/test.go | 29 ++++++++- .../testdata/gno_test/filetest_events.txtar | 33 ++++++++++ .../testdata/gno_test/multitest_events.txtar | 26 ++++++++ gnovm/tests/file.go | 63 ++++++++++++++++++- 9 files changed, 170 insertions(+), 25 deletions(-) create mode 100644 examples/gno.land/r/demo/event/z1_filetest.gno create mode 100644 gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar create mode 100644 gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5b3c3c1fbf1d..77d40098900c 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,7 +47,7 @@ jobs: echo "LOG_LEVEL=debug" >> $GITHUB_ENV echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - run: go install -v ./gnovm/cmd/gno - - run: go run ./gnovm/cmd/gno test -v ./examples/... + - run: go run ./gnovm/cmd/gno test -v -print-events ./examples/... lint: strategy: fail-fast: false diff --git a/examples/gno.land/p/demo/ownable/ownable_test.gno b/examples/gno.land/p/demo/ownable/ownable_test.gno index a9d97154f45c..dee40fa6e1d0 100644 --- a/examples/gno.land/p/demo/ownable/ownable_test.gno +++ b/examples/gno.land/p/demo/ownable/ownable_test.gno @@ -33,15 +33,6 @@ func TestNewWithAddress(t *testing.T) { } } -func TestOwner(t *testing.T) { - std.TestSetRealm(std.NewUserRealm(alice)) - - o := New() - expected := alice - got := o.Owner() - uassert.Equal(t, expected, got) -} - func TestTransferOwnership(t *testing.T) { std.TestSetRealm(std.NewUserRealm(alice)) diff --git a/examples/gno.land/r/demo/event/z1_filetest.gno b/examples/gno.land/r/demo/event/z1_filetest.gno new file mode 100644 index 000000000000..1fcfa1a0e4f4 --- /dev/null +++ b/examples/gno.land/r/demo/event/z1_filetest.gno @@ -0,0 +1,11 @@ +package main + +import "gno.land/r/demo/event" + +func main() { + event.Emit("foo") + event.Emit("bar") +} + +// Events: +// [{"type":"TAG","attrs":[{"key":"key","value":"foo"}],"pkg_path":"gno.land/r/demo/event","func":"Emit"},{"type":"TAG","attrs":[{"key":"key","value":"bar"}],"pkg_path":"gno.land/r/demo/event","func":"Emit"}] diff --git a/examples/gno.land/r/gnoland/events/events.gno b/examples/gno.land/r/gnoland/events/events.gno index 0984edf75a95..baf9ba3d4af2 100644 --- a/examples/gno.land/r/gnoland/events/events.gno +++ b/examples/gno.land/r/gnoland/events/events.gno @@ -73,8 +73,7 @@ func AddEvent(name, description, link, location, startTime, endTime string) (str sort.Sort(events) std.Emit(EventAdded, - "id", - e.id, + "id", e.id, ) return id, nil @@ -92,8 +91,7 @@ func DeleteEvent(id string) { events = append(events[:idx], events[idx+1:]...) std.Emit(EventDeleted, - "id", - e.id, + "id", e.id, ) } @@ -142,8 +140,7 @@ func EditEvent(id string, name, description, link, location, startTime, endTime } std.Emit(EventEdited, - "id", - e.id, + "id", e.id, ) } diff --git a/examples/gno.land/r/gnoland/events/events_test.gno b/examples/gno.land/r/gnoland/events/events_test.gno index 357857352d8c..1d79b754ee4c 100644 --- a/examples/gno.land/r/gnoland/events/events_test.gno +++ b/examples/gno.land/r/gnoland/events/events_test.gno @@ -85,7 +85,8 @@ func TestAddEventErrors(t *testing.T) { } func TestDeleteEvent(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) e1Start := parsedTimeNow.Add(time.Hour * 24 * 5) e1End := e1Start.Add(time.Hour * 4) @@ -107,7 +108,8 @@ func TestDeleteEvent(t *testing.T) { } func TestEditEvent(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) e1Start := parsedTimeNow.Add(time.Hour * 24 * 5) e1End := e1Start.Add(time.Hour * 4) @@ -136,7 +138,8 @@ func TestEditEvent(t *testing.T) { } func TestInvalidEdit(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) uassert.PanicsWithMessage(t, ErrNoSuchID.Error(), func() { EditEvent("123123", "", "", "", "", "", "") @@ -162,9 +165,11 @@ func TestParseTimes(t *testing.T) { } func TestRenderEventWidget(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) // No events yet + events = nil out, err := RenderEventWidget(1) uassert.NoError(t, err) uassert.Equal(t, out, "No events.") diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index af7fa28a14dc..e23f9fa27502 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -21,6 +21,7 @@ import ( gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/tests" + teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/random" @@ -35,6 +36,7 @@ type testCfg struct { timeout time.Duration updateGoldenTests bool printRuntimeMetrics bool + printEvents bool withNativeFallback bool } @@ -149,6 +151,13 @@ func (c *testCfg) RegisterFlags(fs *flag.FlagSet) { false, "print runtime metrics (gas, memory, cpu cycles)", ) + + fs.BoolVar( + &c.printEvents, + "print-events", + false, + "print emitted events", + ) } func execTest(cfg *testCfg, args []string, io commands.IO) error { @@ -228,6 +237,7 @@ func gnoTestPkg( rootDir = cfg.rootDir runFlag = cfg.run printRuntimeMetrics = cfg.printRuntimeMetrics + printEvents = cfg.printEvents stdin = io.In() stdout = io.Out() @@ -295,7 +305,7 @@ func gnoTestPkg( m.Alloc = gno.NewAllocator(maxAllocTx) } m.RunMemPackage(memPkg, true) - err := runTestFiles(m, tfiles, memPkg.Name, verbose, printRuntimeMetrics, runFlag, io) + err := runTestFiles(m, tfiles, memPkg.Name, verbose, printRuntimeMetrics, printEvents, runFlag, io) if err != nil { errs = multierr.Append(errs, err) } @@ -329,7 +339,7 @@ func gnoTestPkg( memPkg.Path = memPkg.Path + "_test" m.RunMemPackage(memPkg, true) - err := runTestFiles(m, ifiles, testPkgName, verbose, printRuntimeMetrics, runFlag, io) + err := runTestFiles(m, ifiles, testPkgName, verbose, printRuntimeMetrics, printEvents, runFlag, io) if err != nil { errs = multierr.Append(errs, err) } @@ -419,6 +429,7 @@ func runTestFiles( pkgName string, verbose bool, printRuntimeMetrics bool, + printEvents bool, runFlag string, io commands.IO, ) (errs error) { @@ -448,10 +459,24 @@ func runTestFiles( m.RunFiles(n) for _, test := range testFuncs.Tests { + // cleanup machine between tests + tests.CleanupMachine(m) + testFuncStr := fmt.Sprintf("%q", test.Name) eval := m.Eval(gno.Call("runtest", testFuncStr)) + if printEvents { + events := m.Context.(*teststd.TestExecContext).EventLogger.Events() + if events != nil { + res, err := json.Marshal(events) + if err != nil { + panic(err) + } + io.ErrPrintfln("EVENTS: %s", string(res)) + } + } + ret := eval[0].GetString() if ret == "" { err := errors.New("failed to execute unit test: %q", test.Name) diff --git a/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar b/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar new file mode 100644 index 000000000000..5e0520a2e855 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar @@ -0,0 +1,33 @@ +# Test with a valid _filetest.gno file + +gno test -print-events . + +! stdout .+ +stderr 'ok \. \d\.\d\ds' + +gno test -print-events -v . + +! stdout .+ +stderr '=== RUN file/valid_filetest.gno' +stderr '--- PASS: file/valid_filetest.gno \(\d\.\d\ds\)' +stderr 'ok \. \d\.\d\ds' + +-- valid.gno -- +package valid + +-- valid_filetest.gno -- +package main + +import "std" + +func main() { + println("test") + std.Emit("EventA") + std.Emit("EventB", "keyA", "valA") +} + +// Output: +// test + +// Events: +// [{"type":"EventA","attrs":[],"pkg_path":"","func":"main"},{"type":"EventB","attrs":[{"key":"keyA","value":"valA"}],"pkg_path":"","func":"main"}] diff --git a/gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar b/gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar new file mode 100644 index 000000000000..321c790561a7 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar @@ -0,0 +1,26 @@ +# Test with a valid _test.gno file + +gno test -print-events . + +! stdout .+ +stderr 'EVENTS: \[{\"type\":\"EventA\",\"attrs\":\[\],\"pkg_path\":\"gno.land/r/.*\",\"func\":\"TestA\"}\]' +stderr 'EVENTS: \[{\"type\":\"EventB\",\"attrs\":\[{\"key\":\"keyA\",\"value\":\"valA\"}\],\"pkg_path\":\"gno.land/r/.*\",\"func\":\"TestB\"},{\"type\":\"EventC\",\"attrs\":\[{\"key\":\"keyD\",\"value\":\"valD\"}\],\"pkg_path\":\"gno.land/r/.*\",\"func\":\"TestB\"}\]' +stderr 'ok \. \d\.\d\ds' + +-- valid.gno -- +package valid + +-- valid_test.gno -- +package valid + +import "testing" +import "std" + +func TestA(t *testing.T) { + std.Emit("EventA") +} + +func TestB(t *testing.T) { + std.Emit("EventB", "keyA", "valA") + std.Emit("EventC", "keyD", "valD") +} diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index f45beffe6480..5449adc01d25 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -2,6 +2,7 @@ package tests import ( "bytes" + "encoding/json" "fmt" "go/ast" "go/parser" @@ -54,7 +55,7 @@ func TestContext(pkgPath string, send std.Coins) *teststd.TestExecContext { pkgAddr := gno.DerivePkgAddr(pkgPath) // the addr of the pkgPath called. caller := gno.DerivePkgAddr("user1.gno") - pkgCoins := std.MustParseCoins(ugnot.ValueString(200000000)).Add(send) // >= send. + pkgCoins := std.MustParseCoins(ugnot.ValueString(200_000_000)).Add(send) // >= send. banker := newTestBanker(pkgAddr.Bech32(), pkgCoins) ctx := stdlibs.ExecContext{ ChainID: "dev", @@ -74,6 +75,19 @@ func TestContext(pkgPath string, send std.Coins) *teststd.TestExecContext { } } +// CleanupMachine can be called during two tests while reusing the same Machine instance. +func CleanupMachine(m *gno.Machine) { + prevCtx := m.Context.(*teststd.TestExecContext) + prevSend := prevCtx.OrigSend + + newCtx := TestContext("", prevCtx.OrigSend) + pkgCoins := std.MustParseCoins(ugnot.ValueString(200_000_000)).Add(prevSend) // >= send. + banker := newTestBanker(prevCtx.OrigPkgAddr, pkgCoins) + newCtx.OrigPkgAddr = prevCtx.OrigPkgAddr + newCtx.Banker = banker + m.Context = newCtx +} + type runFileTestOptions struct { nativeLibs bool logger loggerFunc @@ -110,7 +124,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { opt(&f) } - directives, pkgPath, resWanted, errWanted, rops, stacktraceWanted, maxAlloc, send, preWanted := wantedFromComment(path) + directives, pkgPath, resWanted, errWanted, rops, eventsWanted, stacktraceWanted, maxAlloc, send, preWanted := wantedFromComment(path) if pkgPath == "" { pkgPath = "main" } @@ -347,6 +361,45 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { } } } + case "Events": + // panic if got unexpected error + + if pnc != nil { + if tv, ok := pnc.(*gno.TypedValue); ok { + panic(fmt.Sprintf("fail on %s: got unexpected error: %s", path, tv.Sprint(m))) + } else { // happens on 'unknown import path ...' + panic(fmt.Sprintf("fail on %s: got unexpected error: %v", path, pnc)) + } + } + // check result + events := m.Context.(*teststd.TestExecContext).EventLogger.Events() + evtjson, err := json.Marshal(events) + if err != nil { + panic(err) + } + evtstr := trimTrailingSpaces(string(evtjson)) + if evtstr != eventsWanted { + if f.syncWanted { + // write output to file. + replaceWantedInPlace(path, "Events", evtstr) + } else { + // panic so tests immediately fail (for now). + if eventsWanted == "" { + panic(fmt.Sprintf("fail on %s: got unexpected events: %s", path, evtstr)) + } else { + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(eventsWanted), + B: difflib.SplitLines(evtstr), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + } + } + } case "Realm": // panic if got unexpected error if pnc != nil { @@ -448,7 +501,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { return nil } -func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, stacktrace string, maxAlloc int64, send std.Coins, pre string) { +func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, events, stacktrace string, maxAlloc int64, send std.Coins, pre string) { fset := token.NewFileSet() f, err2 := parser.ParseFile(fset, p, nil, parser.ParseComments) if err2 != nil { @@ -490,6 +543,10 @@ func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, rops = strings.TrimPrefix(text, "Realm:\n") rops = strings.TrimSpace(rops) directives = append(directives, "Realm") + } else if strings.HasPrefix(text, "Events:\n") { + events = strings.TrimPrefix(text, "Events:\n") + events = strings.TrimSpace(events) + directives = append(directives, "Events") } else if strings.HasPrefix(text, "Preprocessed:\n") { pre = strings.TrimPrefix(text, "Preprocessed:\n") pre = strings.TrimSpace(pre) From a2e5c3dda1ce2ef6bdc980e2cabc26ff7ed873d7 Mon Sep 17 00:00:00 2001 From: Morgan Date: Wed, 23 Oct 2024 21:18:38 +0200 Subject: [PATCH 20/31] ci: remove unused goreleaser files, ignore chain/ tags (#3004) I don't know how to test this, but I think this may fix it. @ajnavarro do you have a separate repo / access to the pro token and can see if this configuration works? I removed the other config files as they weren't used, and the `nightly:` section as I don't think it's parsed, anyway: it doesn't exist in the goreleaser schema. --- .github/goreleaser-master.yaml | 503 ------------------ .github/goreleaser-nightly.yaml | 502 ----------------- .github/goreleaser.yaml | 30 +- .../{nightlies.yml => releaser-nightly.yml} | 3 +- 4 files changed, 19 insertions(+), 1019 deletions(-) delete mode 100644 .github/goreleaser-master.yaml delete mode 100644 .github/goreleaser-nightly.yaml rename .github/workflows/{nightlies.yml => releaser-nightly.yml} (99%) diff --git a/.github/goreleaser-master.yaml b/.github/goreleaser-master.yaml deleted file mode 100644 index bca52615db85..000000000000 --- a/.github/goreleaser-master.yaml +++ /dev/null @@ -1,503 +0,0 @@ -project_name: gno - -before: - hooks: - - go mod tidy - -builds: - - id: gno - main: ./gnovm/cmd/gno - binary: gno - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoland - main: ./gno.land/cmd/gnoland - binary: gnoland - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnokey - main: ./gno.land/cmd/gnokey - binary: gnokey - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoweb - main: ./gno.land/cmd/gnoweb - binary: gnoweb - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 -gomod: - proxy: true - -archives: - # https://goreleaser.com/customization/archive/ - - files: - # Standard Release Files - - LICENSE.md - - README.md - -signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - certificate: "${artifact}.pem" - args: - - sign-blob - - "--output-certificate=${certificate}" - - "--output-signature=${signature}" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - artifacts: checksum - output: true - -dockers: - # https://goreleaser.com/customization/docker/ - - # gno - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-amd64" - build_flag_templates: - - "--target=gno" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-arm64v8" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-armv6" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-armv7" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - # gnoland - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-amd64" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-arm64v8" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv6" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv7" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - # gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-amd64" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-arm64v8" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv6" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv7" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - # gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-amd64" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-arm64v8" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv6" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv7" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - -docker_manifests: - # https://goreleaser.com/customization/docker_manifest/ - - # gno - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:master-armv7 - - # gnoland - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv7 - - # gnokey - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv7 - - # gnoweb - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv7 - -docker_signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - artifacts: images - output: true - args: - - "sign" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - -checksum: - name_template: "checksums.txt" - -changelog: - sort: asc - -source: - enabled: true - -sboms: - - artifacts: archive - - id: source # Two different sbom configurations need two different IDs - artifacts: source - -release: - draft: true - replace_existing_draft: true - prerelease: auto - make_latest: false - mode: append - footer: | - ### Container Images - - You can find all docker images at: - - https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} - -nightly: - tag_name: master - publish_release: true - keep_single_release: true - name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-master" \ No newline at end of file diff --git a/.github/goreleaser-nightly.yaml b/.github/goreleaser-nightly.yaml deleted file mode 100644 index 3dac915b7cd7..000000000000 --- a/.github/goreleaser-nightly.yaml +++ /dev/null @@ -1,502 +0,0 @@ -project_name: gno - -before: - hooks: - - go mod tidy - -builds: - - id: gno - main: ./gnovm/cmd/gno - binary: gno - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoland - main: ./gno.land/cmd/gnoland - binary: gnoland - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnokey - main: ./gno.land/cmd/gnokey - binary: gnokey - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoweb - main: ./gno.land/cmd/gnoweb - binary: gnoweb - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 -gomod: - proxy: true - -archives: - # https://goreleaser.com/customization/archive/ - - files: - # Standard Release Files - - LICENSE.md - - README.md - -signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - certificate: "${artifact}.pem" - args: - - sign-blob - - "--output-certificate=${certificate}" - - "--output-signature=${signature}" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - artifacts: checksum - output: true - -dockers: - # https://goreleaser.com/customization/docker/ - - # gno - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-amd64" - build_flag_templates: - - "--target=gno" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-arm64v8" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv6" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv7" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - # gnoland - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-amd64" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-arm64v8" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv6" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv7" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - # gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-amd64" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-arm64v8" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv6" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv7" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - # gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-amd64" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-arm64v8" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv6" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv7" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - -docker_manifests: - # https://goreleaser.com/customization/docker_manifest/ - - # gno - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv7 - - # gnoland - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv7 - - # gnokey - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv7 - - # gnoweb - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv7 - -docker_signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - artifacts: images - output: true - args: - - "sign" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - -checksum: - name_template: "checksums.txt" - -changelog: - sort: asc - -source: - enabled: true - -sboms: - - artifacts: archive - - id: source # Two different sbom configurations need two different IDs - artifacts: source - -release: - draft: true - replace_existing_draft: true - prerelease: auto - mode: append - footer: | - ### Container Images - - You can find all docker images at: - - https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} - -nightly: - tag_name: nightly - publish_release: true - keep_single_release: true - name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-nightly" \ No newline at end of file diff --git a/.github/goreleaser.yaml b/.github/goreleaser.yaml index cd3c62c2ae6f..e2a91ef7ea60 100644 --- a/.github/goreleaser.yaml +++ b/.github/goreleaser.yaml @@ -24,8 +24,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnoland main: ./gno.land/cmd/gnoland binary: gnoland @@ -39,8 +39,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnokey main: ./gno.land/cmd/gnokey binary: gnokey @@ -54,8 +54,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnoweb main: ./gno.land/cmd/gnoweb binary: gnoweb @@ -69,8 +69,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnofaucet dir: ./contribs/gnofaucet binary: gnofaucet @@ -84,8 +84,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnobro dir: ./contribs/gnodev/cmd/gnobro binary: gnobro @@ -99,8 +99,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" gomod: proxy: true @@ -616,7 +616,7 @@ docker_manifests: - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Env.TAG_VERSION }}-arm64v8 - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Env.TAG_VERSION }}-armv6 - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Env.TAG_VERSION }}-armv7 - + # gnoweb - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} image_templates: @@ -704,3 +704,7 @@ nightly: publish_release: true keep_single_release: true name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-{{ .Env.TAG_VERSION }}" + +git: + ignore_tag_prefixes: + - "chain/" diff --git a/.github/workflows/nightlies.yml b/.github/workflows/releaser-nightly.yml similarity index 99% rename from .github/workflows/nightlies.yml rename to .github/workflows/releaser-nightly.yml index 99f9a406ed1f..b53772f5951f 100644 --- a/.github/workflows/nightlies.yml +++ b/.github/workflows/releaser-nightly.yml @@ -34,7 +34,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - + - uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro @@ -44,3 +44,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} TAG_VERSION: nightly + From 4927d4b03f961d164fdce01f9bd0ad192b1e60ee Mon Sep 17 00:00:00 2001 From: Morgan Date: Wed, 23 Oct 2024 22:16:00 +0200 Subject: [PATCH 21/31] ci: fixup goreleaser workflow, again (#3008)
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests
    Co-authored-by: Sergio Maria Matone --- .github/goreleaser.yaml | 2 +- .github/workflows/releaser-nightly.yml | 2 +- .github/workflows/releaser.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/goreleaser.yaml b/.github/goreleaser.yaml index e2a91ef7ea60..b5fb07d05780 100644 --- a/.github/goreleaser.yaml +++ b/.github/goreleaser.yaml @@ -703,7 +703,7 @@ nightly: tag_name: nightly publish_release: true keep_single_release: true - name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-{{ .Env.TAG_VERSION }}" + version_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-{{ .Env.TAG_VERSION }}" git: ignore_tag_prefixes: diff --git a/.github/workflows/releaser-nightly.yml b/.github/workflows/releaser-nightly.yml index b53772f5951f..314c25e3580e 100644 --- a/.github/workflows/releaser-nightly.yml +++ b/.github/workflows/releaser-nightly.yml @@ -39,7 +39,7 @@ jobs: with: distribution: goreleaser-pro version: ~> v2 - args: release --clean --nightly --config ./.github/goreleaser.yaml + args: release --clean --nightly --skip=validate --snapshot --config ./.github/goreleaser.yaml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index 4fb3c279b1f2..057951dbf31e 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -39,7 +39,7 @@ jobs: with: distribution: goreleaser-pro version: ~> v2 - args: release --clean --config ./.github/goreleaser.yaml + args: release --clean --snapshot --config ./.github/goreleaser.yaml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} From c2aef422c2f38240e3fd53aea212473dad9e996b Mon Sep 17 00:00:00 2001 From: Morgan Date: Wed, 23 Oct 2024 22:22:30 +0200 Subject: [PATCH 22/31] ci: fix goreleaser ci again again (#3010)
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests
    --------- Co-authored-by: Sergio Maria Matone --- .github/workflows/releaser-master.yml | 2 +- .github/workflows/releaser-nightly.yml | 5 ++--- .github/workflows/releaser.yml | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/releaser-master.yml b/.github/workflows/releaser-master.yml index 59dc2ec87051..535cac5d965b 100644 --- a/.github/workflows/releaser-master.yml +++ b/.github/workflows/releaser-master.yml @@ -40,7 +40,7 @@ jobs: with: distribution: goreleaser-pro version: ~> v2 - args: release --clean --nightly --config ./.github/goreleaser.yaml + args: release --clean --snapshot --nightly --config ./.github/goreleaser.yaml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/releaser-nightly.yml b/.github/workflows/releaser-nightly.yml index 314c25e3580e..fd4eaa86b0e1 100644 --- a/.github/workflows/releaser-nightly.yml +++ b/.github/workflows/releaser-nightly.yml @@ -2,7 +2,7 @@ name: Trigger nightly build on: schedule: - - cron: '0 0 * * 2-6' + - cron: "0 0 * * 2-6" workflow_dispatch: permissions: @@ -39,9 +39,8 @@ jobs: with: distribution: goreleaser-pro version: ~> v2 - args: release --clean --nightly --skip=validate --snapshot --config ./.github/goreleaser.yaml + args: release --clean --nightly --snapshot --config ./.github/goreleaser.yaml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} TAG_VERSION: nightly - diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index 057951dbf31e..8bbc9323cad5 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -34,12 +34,12 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - + - uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro version: ~> v2 - args: release --clean --snapshot --config ./.github/goreleaser.yaml + args: release --clean --config ./.github/goreleaser.yaml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} From 520195e3747e2c749a100a53adbf7fb30d6edbba Mon Sep 17 00:00:00 2001 From: Miguel Victoria Villaquiran Date: Wed, 23 Oct 2024 22:24:49 +0200 Subject: [PATCH 23/31] feat(stdlibs/std): prohibit getting Banker from a pure package (#2248) Related to #2192 - Trigger a panic if a p/ attempts to create a banker, but allow interaction with an already instantiated banker from r/. Don't really know if this is the right approach. If you have another idea of how to implement this security check please let me know :)
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
    --------- Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> --- .../gno.land/r/demo/banktest/z_0_filetest.gno | 11 +++++-- .../gno.land/r/demo/banktest/z_1_filetest.gno | 7 ++++- .../gno.land/r/demo/banktest/z_2_filetest.gno | 11 +++++-- .../gno.land/r/demo/banktest/z_3_filetest.gno | 11 +++++-- .../gno.land/r/demo/disperse/z_0_filetest.gno | 4 ++- .../gno.land/r/demo/disperse/z_1_filetest.gno | 4 ++- .../gno.land/r/demo/disperse/z_2_filetest.gno | 4 ++- .../gno.land/r/demo/disperse/z_3_filetest.gno | 4 ++- .../gno.land/r/demo/disperse/z_4_filetest.gno | 4 ++- gnovm/Makefile | 2 +- gnovm/stdlibs/generated.go | 12 ++++++++ gnovm/stdlibs/std/banker.gno | 1 + gnovm/stdlibs/std/native.gno | 1 + gnovm/stdlibs/std/native.go | 7 +++++ gnovm/tests/files/stdbanker_stdlibs.gno | 13 ++++++++ gnovm/tests/stdlibs/generated.go | 30 +++++++++++++++++++ gnovm/tests/stdlibs/std/frame_testing.gno | 3 ++ gnovm/tests/stdlibs/std/std.gno | 1 + gnovm/tests/stdlibs/std/std.go | 4 +++ 19 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 gnovm/tests/files/stdbanker_stdlibs.gno diff --git a/examples/gno.land/r/demo/banktest/z_0_filetest.gno b/examples/gno.land/r/demo/banktest/z_0_filetest.gno index 4ea76bbe17ab..61289dfe0718 100644 --- a/examples/gno.land/r/demo/banktest/z_0_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_0_filetest.gno @@ -1,6 +1,11 @@ +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + // SEND: 100000000ugnot -package main +package bank1 import ( "std" @@ -11,7 +16,7 @@ import ( func main() { // set up main address and banktest addr. banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/bank1") std.TestSetOrigCaller(mainaddr) std.TestSetOrigPkgAddr(banktestAddr) @@ -42,7 +47,7 @@ func main() { // main after: 250000000ugnot // ## recent activity // -// * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 50000000ugnot returned, at 2009-02-13 11:31pm UTC +// * g1tnpdmvrmtgql8fmxgsq9rwtst5hsxahk3f05dk 100000000ugnot sent, 50000000ugnot returned, at 2009-02-13 11:31pm UTC // // ## total deposits // 50000000ugnot diff --git a/examples/gno.land/r/demo/banktest/z_1_filetest.gno b/examples/gno.land/r/demo/banktest/z_1_filetest.gno index 8f9f76470364..39682d263305 100644 --- a/examples/gno.land/r/demo/banktest/z_1_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_1_filetest.gno @@ -1,4 +1,9 @@ -package main +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + +package bank1 import ( "std" diff --git a/examples/gno.land/r/demo/banktest/z_2_filetest.gno b/examples/gno.land/r/demo/banktest/z_2_filetest.gno index a0280e0d75b5..2dc9c84e7670 100644 --- a/examples/gno.land/r/demo/banktest/z_2_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_2_filetest.gno @@ -1,4 +1,9 @@ -package main +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + +package bank1 import ( "std" @@ -10,7 +15,7 @@ func main() { banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") // print main balance before. - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/bank1") std.TestSetOrigCaller(mainaddr) banker := std.GetBanker(std.BankerTypeReadonly) @@ -39,7 +44,7 @@ func main() { // main after: 255000000ugnot // ## recent activity // -// * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 55000000ugnot returned, at 2009-02-13 11:31pm UTC +// * g1tnpdmvrmtgql8fmxgsq9rwtst5hsxahk3f05dk 100000000ugnot sent, 55000000ugnot returned, at 2009-02-13 11:31pm UTC // // ## total deposits // 45000000ugnot diff --git a/examples/gno.land/r/demo/banktest/z_3_filetest.gno b/examples/gno.land/r/demo/banktest/z_3_filetest.gno index ca8717dfcc93..7b6758c3e4f8 100644 --- a/examples/gno.land/r/demo/banktest/z_3_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_3_filetest.gno @@ -1,4 +1,9 @@ -package main +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + +package bank1 import ( "std" @@ -7,7 +12,7 @@ import ( func main() { banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/bank1") std.TestSetOrigCaller(mainaddr) banker := std.GetBanker(std.BankerTypeRealmSend) @@ -17,4 +22,4 @@ func main() { } // Error: -// can only send coins from realm that created banker "g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4", not "g1dv3435088tlrgggf745kaud0ptrkc9v42k8llz" +// can only send coins from realm that created banker "g1tnpdmvrmtgql8fmxgsq9rwtst5hsxahk3f05dk", not "g1dv3435088tlrgggf745kaud0ptrkc9v42k8llz" diff --git a/examples/gno.land/r/demo/disperse/z_0_filetest.gno b/examples/gno.land/r/demo/disperse/z_0_filetest.gno index 62a34cfdf26c..e54b34ae3bf1 100644 --- a/examples/gno.land/r/demo/disperse/z_0_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_0_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 200ugnot package main @@ -10,7 +12,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") std.TestSetOrigPkgAddr(disperseAddr) std.TestSetOrigCaller(mainaddr) diff --git a/examples/gno.land/r/demo/disperse/z_1_filetest.gno b/examples/gno.land/r/demo/disperse/z_1_filetest.gno index 1e042d320f68..62018fe965e6 100644 --- a/examples/gno.land/r/demo/disperse/z_1_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_1_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -10,7 +12,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") std.TestSetOrigPkgAddr(disperseAddr) std.TestSetOrigCaller(mainaddr) diff --git a/examples/gno.land/r/demo/disperse/z_2_filetest.gno b/examples/gno.land/r/demo/disperse/z_2_filetest.gno index 163bb2fc1abc..79e8d81e2b13 100644 --- a/examples/gno.land/r/demo/disperse/z_2_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_2_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -10,7 +12,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") std.TestSetOrigPkgAddr(disperseAddr) std.TestSetOrigCaller(mainaddr) diff --git a/examples/gno.land/r/demo/disperse/z_3_filetest.gno b/examples/gno.land/r/demo/disperse/z_3_filetest.gno index eabed52fb38b..7cb7ffbe71d5 100644 --- a/examples/gno.land/r/demo/disperse/z_3_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_3_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -11,7 +13,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") beneficiary1 := std.Address("g1dmt3sa5ucvecxuhf3j6ne5r0e3z4x7h6c03xc0") beneficiary2 := std.Address("g1akeqsvhucjt8gf5yupyzjxsjd29wv8fayng37c") diff --git a/examples/gno.land/r/demo/disperse/z_4_filetest.gno b/examples/gno.land/r/demo/disperse/z_4_filetest.gno index ebf4bed4473a..4dafb780e831 100644 --- a/examples/gno.land/r/demo/disperse/z_4_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_4_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -11,7 +13,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") beneficiary1 := std.Address("g1dmt3sa5ucvecxuhf3j6ne5r0e3z4x7h6c03xc0") beneficiary2 := std.Address("g1akeqsvhucjt8gf5yupyzjxsjd29wv8fayng37c") diff --git a/gnovm/Makefile b/gnovm/Makefile index 5ff3af9c253b..d27395d9cd1e 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -54,7 +54,7 @@ lint: .PHONY: fmt fmt: - go run ./cmd/gno fmt $(GNOFMT_FLAGS) ./stdlibs/... + go run ./cmd/gno fmt $(GNOFMT_FLAGS) ./stdlibs/... ./tests/stdlibs/... $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . .PHONY: imports diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index b0788fc6d1ba..a2d82b0bc600 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -720,6 +720,18 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "std", + "assertCallerIsRealm", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + libs_std.X_assertCallerIsRealm( + m, + ) + }, + }, { "std", "setParamString", diff --git a/gnovm/stdlibs/std/banker.gno b/gnovm/stdlibs/std/banker.gno index 2b94292bd7e4..5412b73281ca 100644 --- a/gnovm/stdlibs/std/banker.gno +++ b/gnovm/stdlibs/std/banker.gno @@ -65,6 +65,7 @@ func (b BankerType) String() string { // GetBanker returns a new Banker, with its capabilities matching the given // [BankerType]. func GetBanker(bt BankerType) Banker { + assertCallerIsRealm() if bt >= maxBanker { panic("invalid banker type") } diff --git a/gnovm/stdlibs/std/native.gno b/gnovm/stdlibs/std/native.gno index 22a16fc18d1d..5421e231de2a 100644 --- a/gnovm/stdlibs/std/native.gno +++ b/gnovm/stdlibs/std/native.gno @@ -65,3 +65,4 @@ func getRealm(height int) (address string, pkgPath string) func derivePkgAddr(pkgPath string) string func encodeBech32(prefix string, bz [20]byte) string func decodeBech32(addr string) (prefix string, bz [20]byte, ok bool) +func assertCallerIsRealm() diff --git a/gnovm/stdlibs/std/native.go b/gnovm/stdlibs/std/native.go index f185a52f2493..3fe5fbb9889e 100644 --- a/gnovm/stdlibs/std/native.go +++ b/gnovm/stdlibs/std/native.go @@ -158,6 +158,13 @@ func X_decodeBech32(addr string) (prefix string, bytes [20]byte, ok bool) { return prefix, [20]byte(bz), true } +func X_assertCallerIsRealm(m *gno.Machine) { + frame := m.Frames[m.NumFrames()-2] + if path := frame.LastPackage.PkgPath; !gno.IsRealmPath(path) { + m.Panic(typedString("caller is not a realm")) + } +} + func typedString(s string) gno.TypedValue { tv := gno.TypedValue{T: gno.StringType} tv.SetString(gno.StringValue(s)) diff --git a/gnovm/tests/files/stdbanker_stdlibs.gno b/gnovm/tests/files/stdbanker_stdlibs.gno new file mode 100644 index 000000000000..d0872dd38e63 --- /dev/null +++ b/gnovm/tests/files/stdbanker_stdlibs.gno @@ -0,0 +1,13 @@ +package main + +import "std" + +func main() { + defer func() { + println(recover()) + }() + std.TestSetRealm(std.NewCodeRealm("gno.land/p/demo/users")) +} + +// Output: +// should only be called for Realms diff --git a/gnovm/tests/stdlibs/generated.go b/gnovm/tests/stdlibs/generated.go index 23bb3cfa5943..f3d74e214eb3 100644 --- a/gnovm/tests/stdlibs/generated.go +++ b/gnovm/tests/stdlibs/generated.go @@ -296,6 +296,36 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "std", + "isRealm", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{ + {Name: gno.N("r0"), Type: gno.X("bool")}, + }, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + + r0 := testlibs_std.X_isRealm( + m, + p0) + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + }, + }, { "testing", "unixNano", diff --git a/gnovm/tests/stdlibs/std/frame_testing.gno b/gnovm/tests/stdlibs/std/frame_testing.gno index 171756c54f5f..f9952969497b 100644 --- a/gnovm/tests/stdlibs/std/frame_testing.gno +++ b/gnovm/tests/stdlibs/std/frame_testing.gno @@ -8,5 +8,8 @@ func NewUserRealm(user Address) Realm { // NewCodeRealm creates a new realm for a published code realm with the given // pkgPath. func NewCodeRealm(pkgPath string) Realm { + if !isRealm(pkgPath) { + panic("should only be called for Realms") + } return Realm{pkgPath: pkgPath, addr: DerivePkgAddr(pkgPath)} } diff --git a/gnovm/tests/stdlibs/std/std.gno b/gnovm/tests/stdlibs/std/std.gno index f583342ae045..3a56ecc1c473 100644 --- a/gnovm/tests/stdlibs/std/std.gno +++ b/gnovm/tests/stdlibs/std/std.gno @@ -38,3 +38,4 @@ func testSetOrigSend( spentDenom []string, spentAmt []int64) func testIssueCoins(addr string, denom []string, amt []int64) func getRealm(height int) (address string, pkgPath string) +func isRealm(pkgPath string) bool diff --git a/gnovm/tests/stdlibs/std/std.go b/gnovm/tests/stdlibs/std/std.go index 0421f359932a..d580572e9c54 100644 --- a/gnovm/tests/stdlibs/std/std.go +++ b/gnovm/tests/stdlibs/std/std.go @@ -173,6 +173,10 @@ func X_getRealm(m *gno.Machine, height int) (address string, pkgPath string) { return string(ctx.OrigCaller), "" } +func X_isRealm(m *gno.Machine, pkgPath string) bool { + return gno.IsRealmPath(pkgPath) +} + func X_testSetOrigSend(m *gno.Machine, sentDenom []string, sentAmt []int64, spentDenom []string, spentAmt []int64, From 287c22ec830a1408f1d3de6319602640d841c7cc Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Wed, 23 Oct 2024 23:09:04 -0500 Subject: [PATCH 24/31] fix(gnovm): fix issue with locally re-definition (#3014) closes: https://github.com/gnolang/gno/issues/3013
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests
    --------- Co-authored-by: Morgan Bazalgette --- gnovm/pkg/gnolang/preprocess.go | 7 +------ gnovm/tests/files/redefine.gno | 15 +++++++++++++++ gnovm/tests/files/redefine2.gno | 25 +++++++++++++++++++++++++ gnovm/tests/files/redefine3.gno | 13 +++++++++++++ gnovm/tests/files/redefine4.gno | 15 +++++++++++++++ gnovm/tests/files/redefine5.gno | 18 ++++++++++++++++++ gnovm/tests/files/redefine6.gno | 9 +++++++++ 7 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 gnovm/tests/files/redefine.gno create mode 100644 gnovm/tests/files/redefine2.gno create mode 100644 gnovm/tests/files/redefine3.gno create mode 100644 gnovm/tests/files/redefine4.gno create mode 100644 gnovm/tests/files/redefine5.gno create mode 100644 gnovm/tests/files/redefine6.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e1dc3671333a..04cc83b54f01 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -157,7 +157,6 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { switch n := n.(type) { case *AssignStmt: if n.Op == DEFINE { - var defined bool for _, lx := range n.Lhs { nx := lx.(*NameExpr) ln := nx.Name @@ -165,16 +164,12 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { continue } if !isLocallyDefined2(last, ln) { - // if loop extern, will change to + // if loop extern, will promote to // NameExprTypeHeapDefine later. nx.Type = NameExprTypeDefine last.Predefine(false, ln) - defined = true } } - if !defined { - panic(fmt.Sprintf("nothing defined in assignment %s", n.String())) - } } case *ImportDecl: nx := &n.NameExpr diff --git a/gnovm/tests/files/redefine.gno b/gnovm/tests/files/redefine.gno new file mode 100644 index 000000000000..62eea61f25e6 --- /dev/null +++ b/gnovm/tests/files/redefine.gno @@ -0,0 +1,15 @@ +package main + +var ss = []int{1, 2, 3} + +func main() { + for _, s := range ss { + s := s + println(s) + } +} + +// Output: +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/redefine2.gno b/gnovm/tests/files/redefine2.gno new file mode 100644 index 000000000000..b0621fe2a035 --- /dev/null +++ b/gnovm/tests/files/redefine2.gno @@ -0,0 +1,25 @@ +package main + +var testTable = []struct { + name string +}{ + { + "one", + }, + { + "two", + }, +} + +func main() { + + for _, testCase := range testTable { + testCase := testCase + + println(testCase.name) + } +} + +// Output: +// one +// two diff --git a/gnovm/tests/files/redefine3.gno b/gnovm/tests/files/redefine3.gno new file mode 100644 index 000000000000..7a2d0859f5c1 --- /dev/null +++ b/gnovm/tests/files/redefine3.gno @@ -0,0 +1,13 @@ +package main + +func main() { + for i := 0; i < 3; i++ { + i := i + println(i) + } +} + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/redefine4.gno b/gnovm/tests/files/redefine4.gno new file mode 100644 index 000000000000..db310fae3c20 --- /dev/null +++ b/gnovm/tests/files/redefine4.gno @@ -0,0 +1,15 @@ +package main + +func main() { + a := 1 + b := 3 + println(a, b) // prints 1 3 + + // Re-declaration of 'a' is allowed because 'c' is a new variable + a, c := 2, 5 + println(a, c) // prints 2 5 +} + +// Output: +// 1 3 +// 2 5 diff --git a/gnovm/tests/files/redefine5.gno b/gnovm/tests/files/redefine5.gno new file mode 100644 index 000000000000..9637df913f0e --- /dev/null +++ b/gnovm/tests/files/redefine5.gno @@ -0,0 +1,18 @@ +package main + +func main() { + a := 1 + println(a) // prints 1 + + if true { + a := 2 // valid: new scope inside the if statement + println(a) // prints 2 + } + + println(a) // prints 1: outer variable is unchanged +} + +// Output: +// 1 +// 2 +// 1 diff --git a/gnovm/tests/files/redefine6.gno b/gnovm/tests/files/redefine6.gno new file mode 100644 index 000000000000..ff5ca97d063f --- /dev/null +++ b/gnovm/tests/files/redefine6.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a, b := 1, 2 + a, b := 3, 4 +} + +// Error: +// files/redefine6.gno:5:2: no new variables on left side of := From a478348dec4f07373dfefd614ef8682e34ae7278 Mon Sep 17 00:00:00 2001 From: Nemanja Aleksic Date: Fri, 25 Oct 2024 09:32:37 -0500 Subject: [PATCH 25/31] chore: remove CODEOWNERS (#3022) Remove all teams and individuals in CODEOWNERS Related to https://github.com/gnolang/gno/issues/3019 --- .github/CODEOWNERS | 97 ---------------------------------------------- 1 file changed, 97 deletions(-) delete mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index bafaa70301b3..000000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,97 +0,0 @@ -# CODEOWNERS: https://help.github.com/articles/about-codeowners/ - -# Primary repo maintainers. -* @gnolang/tech-staff - -# Tendermint2. -/tm2/ @jaekwon @moul @piux2 @zivkovicmilos -/tm2/pkg/crypto/ @jaekwon @moul @gnolang/security -/tm2/pkg/crypto/keys/client/ @jaekwon @gnolang/security -/tm2/pkg/db/ @ajnavarro -# TODO: add per package exceptions -# ... - -# Docs & Content. -/docs/ @moul -/docs/**.md @gnolang/devrels -/docs/**.gif @gnolang/devrels -/docs/Makefile @gnolang/devrels -/README.md @moul @gnolang/devrels -/**/README.md @gnolang/devrels -/.gitpod.yml @gnolang/devrels - -# Gno examples and default contracts. -/examples/ @gnolang/tech-staff @gnolang/devrels -/examples/gno.land/p/demo/ @gnolang/tech-staff @gnolang/devrels -/examples/gno.land/p/demo/avl/ @jaekwon -/examples/gno.land/p/demo/bf/ @moul -/examples/gno.land/p/demo/blog/ @gnolang/devrels -/examples/gno.land/p/demo/boardsv2/ @ilgooz @jeronimoalbi @moul -/examples/gno.land/p/demo/cford32/ @thehowl -/examples/gno.land/p/demo/memeland/ @leohhhn -/examples/gno.land/p/demo/seqid/ @thehowl -/examples/gno.land/p/demo/ownable/ @leohhhn -/examples/gno.land/p/demo/pausable/ @leohhhn -/examples/gno.land/p/demo/svg/ @moul -/examples/gno.land/p/demo/tamagotchi/ @moul -/examples/gno.land/p/demo/ui/ @moul -/examples/gno.land/r/demo/ @gnolang/tech-staff @gnolang/devrels -/examples/gno.land/r/demo/art/ @moul -/examples/gno.land/r/demo/boardsv2/ @ilgooz @jeronimoalbi @moul -/examples/gno.land/r/demo/memeland/ @leohhhn -/examples/gno.land/r/demo/tamagotchi/ @moul -/examples/gno.land/r/demo/userbook/ @leohhhn -/examples/gno.land/r/gnoland/ @moul -/examples/gno.land/r/sys/ @moul -/examples/gno.land/r/jaekwon/ @jaekwon -/examples/gno.land/r/manfred/ @moul - -# Gno.land. -/gno.land/ @moul @zivkovicmilos -/gno.land/cmd/genesis/ @zivkovicmilos -/gno.land/cmd/gnokey/ @jaekwon @moul @gfanton -/gno.land/cmd/gnoland/ @zivkovicmilos @gnolang/devops -/gno.land/cmd/gnoweb/ @gfanton @thehowl @alexiscolin -/gno.land/pkg/gnoclient/ @zivkovicmilos @leohhhn @gfanton -/gno.land/pkg/gnoland/ @zivkovicmilos @gfanton -/gno.land/pkg/keyscli/ @jaekwon @moul @gfanton -/gno.land/pkg/log/ @zivkovicmilos @gfanton -/gno.land/pkg/sdk/vm/ @moul @gfanton @thehowl -/gno.land/pkg/integration/ @gfanton -/gno.land/genesis/ @moul -#... - -# GnoVM/Gnolang. -/gnovm/ @jaekwon @moul @piux2 @thehowl -/gnovm/stdlibs/ @thehowl -/gnovm/tests/ @jaekwon @thehowl @mvertes -/gnovm/cmd/gno/ @moul @thehowl -/gnovm/pkg/gnolang/ @jaekwon @moul @piux2 -/gnovm/pkg/doc/ @thehowl -/gnovm/pkg/repl/ @mvertes @ajnavarro -/gnovm/pkg/gnomod/ @thehowl -/gnovm/pkg/gnoenv/ @gfanton -/gnovm/pkg/transpiler/ @thehowl -/gnovm/pkg/integration/ @gfanton - -# Contribs -/contribs/ @gnolang/tech-staff -/contribs/gnodev/ @gfanton -/contribs/gnokeykc/ @moul -/contribs/gnomd/ @moul - -# Misc -/misc/ @gnolang/tech-staff -/misc/loop/ @moul @gnolang/devops -/misc/deployments/ @moul @gnolang/devops -/misc/genstd/ @thehowl - -# Special files. -/PLAN.md @jaekwon @moul -/PHILOSOPHY.md @jaekwon -/CONTRIBUTING.md @jaekwon @moul @gnolang/tech-staff -/LICENSE.md @jaekwon -/.github/ @moul @gnolang/tech-staff -/.github/workflows @ajnavarro @moul -/.github/CODEOWNERS @jaekwon @moul -/go.mod @gnolang/tech-staff # no unnecessary dependencies From 0b2c67ed3883bd04d0a03eb8c85ce218616099c2 Mon Sep 17 00:00:00 2001 From: Morgan Date: Fri, 25 Oct 2024 13:26:12 -0500 Subject: [PATCH 26/31] fix(gnolang): ensure complete Uverse initialization (#2997) Fixes #2067. UverseNode now distinguishes when it's uninitialized, initializing and initialized. In combination with calling Uverse() at init, we make sure that after package initialization we always have the same result from Uverse() and UverseNode() and we don't have issues like those pointed out in #2067. --- gnovm/pkg/gnolang/gno_test.go | 12 --------- gnovm/pkg/gnolang/preprocess.go | 6 +---- gnovm/pkg/gnolang/uverse.go | 47 ++++++++++++++++++++++++++------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 1f83303023c4..3b15c018505f 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -404,18 +404,6 @@ func BenchmarkBenchdata(b *testing.B) { name += "_param:" + param } b.Run(name, func(b *testing.B) { - if strings.HasPrefix(name, "matrix.gno_param") { - // CGO_ENABLED=0 go test -bench . -benchmem ./... -short -run=^$ -cpu 1,2 -count=1 ./... - // That is not just exposing test and benchmark traces as output, but these benchmarks are failing - // making the output unparseable: - /* - BenchmarkBenchdata/matrix.gno_param:3 panic: runtime error: index out of range [31] with length 25 [recovered] - panic: runtime error: index out of range [31] with length 25: - ... - */ - b.Skip("it panics causing an error when parsing benchmark results") - } - // Gen template with N and param. var buf bytes.Buffer require.NoError(b, tpl.Execute(&buf, bdataParams{ diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 04cc83b54f01..2d65dfa5cb15 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -734,12 +734,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *FuncDecl: // retrieve cached function type. + // the type and receiver are already set in predefineNow. ft := getType(&n.Type).(*FuncType) - if n.IsMethod { - // recv/type set @ predefineNow(). - } else { - // type set @ predefineNow(). - } // push func body block. pushInitBlock(n, &last, &stack) diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index d62d4228d686..ba66b27499f2 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -61,26 +61,55 @@ var gStringerType = &DeclaredType{ var ( uverseNode *PackageNode uverseValue *PackageValue + uverseInit = uverseUninitialized ) +const ( + uverseUninitialized = iota + uverseInitializing + uverseInitialized +) + +func init() { + // Call Uverse() so we initialize the Uverse node ahead of any calls to the package. + Uverse() +} + const uversePkgPath = ".uverse" -// Always returns a new copy from the latest state of source. +// UverseNode returns the uverse PackageValue. +// If called while initializing the UverseNode itself, it will return an empty +// PackageValue. func Uverse() *PackageValue { - if uverseValue == nil { - pn := UverseNode() - uverseValue = pn.NewPackage() + switch uverseInit { + case uverseUninitialized: + uverseInit = uverseInitializing + makeUverseNode() + uverseInit = uverseInitialized + case uverseInitializing: + return &PackageValue{} } + return uverseValue } -// Always returns the same instance with possibly differing completeness. +// UverseNode returns the uverse PackageNode. +// If called while initializing the UverseNode itself, it will return an empty +// PackageNode. func UverseNode() *PackageNode { - // Global is singleton. - if uverseNode != nil { - return uverseNode + switch uverseInit { + case uverseUninitialized: + uverseInit = uverseInitializing + makeUverseNode() + uverseInit = uverseInitialized + case uverseInitializing: + return &PackageNode{} } + return uverseNode +} + +func makeUverseNode() { // NOTE: uverse node is hidden, thus the leading dot in pkgPath=".uverse". uverseNode = NewPackageNode("uverse", uversePkgPath, nil) @@ -1017,7 +1046,7 @@ func UverseNode() *PackageNode { m.Exceptions = nil }, ) - return uverseNode + uverseValue = uverseNode.NewPackage() } func copyDataToList(dst []TypedValue, data []byte, et Type) { From 603f6d3a5a4856f4f1b60b4643e253c9e8956c57 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:27:45 -0500 Subject: [PATCH 27/31] chore: relocate tm2/std.MemFile in gnovm/std (#2910) This PR removes "gno.land" from all `tm2/.../*.go` files. --------- Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoclient/client_test.go | 51 +- gno.land/pkg/gnoclient/integration_test.go | 30 +- gno.land/pkg/gnoland/app_test.go | 13 +- gno.land/pkg/gnoweb/gnoweb.go | 4 +- gno.land/pkg/keyscli/run.go | 7 +- gno.land/pkg/sdk/vm/gas_test.go | 7 +- gno.land/pkg/sdk/vm/keeper.go | 3 +- gno.land/pkg/sdk/vm/keeper_test.go | 25 +- gno.land/pkg/sdk/vm/msg_test.go | 15 +- gno.land/pkg/sdk/vm/msgs.go | 21 +- gno.land/pkg/sdk/vm/package.go | 2 + gno.land/pkg/sdk/vm/vm.proto | 10 +- gnovm/cmd/gno/test.go | 6 +- gnovm/gno.proto | 14 +- gnovm/gnovm.proto | 16 + {tm2/pkg/std => gnovm}/memfile.go | 2 +- {tm2/pkg/std => gnovm}/memfile_test.go | 2 +- gnovm/package.go | 15 + gnovm/pkg/gnolang/gnolang.proto | 21 +- gnovm/pkg/gnolang/go2gno.go | 8 +- gnovm/pkg/gnolang/go2gno_test.go | 72 +- gnovm/pkg/gnolang/machine.go | 10 +- gnovm/pkg/gnolang/machine_test.go | 10 +- gnovm/pkg/gnolang/nodes.go | 16 +- gnovm/pkg/gnolang/store.go | 24 +- gnovm/pkg/gnolang/store_test.go | 10 +- gnovm/pkg/gnomod/gnomod.go | 4 +- gnovm/tests/file.go | 5 +- misc/genproto/Makefile | 4 + misc/genproto/genproto.go | 2 + tm2/pkg/amino/tests/pb/tests.pb.go | 5582 ----------------- tm2/pkg/amino/tests/proto3/proto/compat.pb.go | 1044 --- tm2/pkg/libtm/messages/types/messages.pb.go | 543 -- tm2/pkg/std/package.go | 4 - tm2/pkg/std/std.proto | 11 - tm2/pkg/telemetry/config/config.go | 6 +- 36 files changed, 254 insertions(+), 7365 deletions(-) create mode 100644 gnovm/gnovm.proto rename {tm2/pkg/std => gnovm}/memfile.go (99%) rename {tm2/pkg/std => gnovm}/memfile_test.go (99%) create mode 100644 gnovm/package.go delete mode 100644 tm2/pkg/amino/tests/pb/tests.pb.go delete mode 100644 tm2/pkg/amino/tests/proto3/proto/compat.pb.go delete mode 100644 tm2/pkg/libtm/messages/types/messages.pb.go diff --git a/gno.land/pkg/gnoclient/client_test.go b/gno.land/pkg/gnoclient/client_test.go index b7eb21837a7d..1f8563d34fea 100644 --- a/gno.land/pkg/gnoclient/client_test.go +++ b/gno.land/pkg/gnoclient/client_test.go @@ -8,6 +8,7 @@ import ( "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -17,7 +18,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) -var testGasFee = ugnot.ValueString(10000) +var testGasFee = ugnot.ValueString(10_000) func TestRender(t *testing.T) { t.Parallel() @@ -652,8 +653,8 @@ func main() { msg := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ - Files: []*std.MemFile{ + Package: &gnovm.MemPackage{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody, @@ -729,8 +730,8 @@ func main() { msg1 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ - Files: []*std.MemFile{ + Package: &gnovm.MemPackage{ + Files: []*gnovm.MemFile{ { Name: "main1.gno", Body: fileBody, @@ -742,8 +743,8 @@ func main() { msg2 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ - Files: []*std.MemFile{ + Package: &gnovm.MemPackage{ + Files: []*gnovm.MemFile{ { Name: "main2.gno", Body: fileBody, @@ -794,10 +795,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -841,10 +842,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -872,10 +873,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -903,10 +904,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -943,7 +944,7 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{Name: "", Path: " "}, + Package: &gnovm.MemPackage{Name: "", Path: " "}, Send: nil, }, }, @@ -993,10 +994,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1040,10 +1041,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1071,10 +1072,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1102,10 +1103,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1142,7 +1143,7 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{Name: "", Path: ""}, + Package: &gnovm.MemPackage{Name: "", Path: ""}, Deposit: nil, }, }, diff --git a/gno.land/pkg/gnoclient/integration_test.go b/gno.land/pkg/gnoclient/integration_test.go index 846962766f82..0a06eb4756a3 100644 --- a/gno.land/pkg/gnoclient/integration_test.go +++ b/gno.land/pkg/gnoclient/integration_test.go @@ -5,17 +5,17 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/tm2/pkg/sdk/bank" - "github.com/gnolang/gno/tm2/pkg/std" - "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/gno.land/pkg/integration" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/keys" "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -316,9 +316,9 @@ func main() { // Make Msg configs msg := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody, @@ -393,9 +393,9 @@ func main() { // Make Msg configs msg1 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody1, @@ -406,9 +406,9 @@ func main() { } msg2 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody2, @@ -474,10 +474,10 @@ func Echo(str string) string { // Make Msg config msg := vm.MsgAddPackage{ Creator: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "echo", Path: deploymentPath, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: fileName, Body: body, @@ -564,10 +564,10 @@ func Hello(str string) string { msg1 := vm.MsgAddPackage{ Creator: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "echo", Path: deploymentPath1, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "echo.gno", Body: body1, @@ -579,10 +579,10 @@ func Hello(str string) string { msg2 := vm.MsgAddPackage{ Creator: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "hello", Path: deploymentPath2, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "gno.mod", Body: "module gno.land/p/demo/integration/test/hello", diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index 193ff0b0b142..87b624280c66 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -9,7 +9,8 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - gnostd "github.com/gnolang/gno/gnovm/stdlibs/std" + "github.com/gnolang/gno/gnovm" + gnostdlibs "github.com/gnolang/gno/gnovm/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" bft "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -53,7 +54,7 @@ func TestNewAppWithOptions(t *testing.T) { }, Txs: []std.Tx{ { - Msgs: []std.Msg{vm.NewMsgAddPackage(addr, "gno.land/r/demo", []*std.MemFile{ + Msgs: []std.Msg{vm.NewMsgAddPackage(addr, "gno.land/r/demo", []*gnovm.MemFile{ { Name: "demo.gno", Body: "package demo; func Hello() string { return `hello`; }", @@ -308,7 +309,7 @@ func TestEndBlocker(t *testing.T) { c := newCollector[validatorUpdate](mockEventSwitch, noFilter) // Fire a GnoVM event - mockEventSwitch.FireEvent(gnostd.GnoEvent{}) + mockEventSwitch.FireEvent(gnostdlibs.GnoEvent{}) // Create the EndBlocker eb := EndBlocker(c, mockVMKeeper, &mockEndBlockerApp{}) @@ -351,7 +352,7 @@ func TestEndBlocker(t *testing.T) { c := newCollector[validatorUpdate](mockEventSwitch, noFilter) // Fire a GnoVM event - mockEventSwitch.FireEvent(gnostd.GnoEvent{}) + mockEventSwitch.FireEvent(gnostdlibs.GnoEvent{}) // Create the EndBlocker eb := EndBlocker(c, mockVMKeeper, &mockEndBlockerApp{}) @@ -390,7 +391,7 @@ func TestEndBlocker(t *testing.T) { // Construct the GnoVM events vmEvents := make([]abci.Event, 0, len(changes)) for index := range changes { - event := gnostd.GnoEvent{ + event := gnostdlibs.GnoEvent{ Type: validatorAddedEvent, PkgPath: valRealm, } @@ -399,7 +400,7 @@ func TestEndBlocker(t *testing.T) { if index%2 == 0 { changes[index].Power = 0 - event = gnostd.GnoEvent{ + event = gnostdlibs.GnoEvent{ Type: validatorRemovedEvent, PkgPath: valRealm, } diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index c0bc24ce2160..ed6271f5afec 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -18,10 +18,10 @@ import ( "strings" "time" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gorilla/mux" "github.com/gotuna/gotuna" @@ -389,7 +389,7 @@ func handlerPackageFile(logger *slog.Logger, app gotuna.App, cfg *Config) http.H return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) pkgpath := "gno.land/p/" + vars["filepath"] - diruri, filename := std.SplitFilepath(pkgpath) + diruri, filename := gnovm.SplitFilepath(pkgpath) if filename == "" && diruri == pkgpath { // redirect to diruri + "/" http.Redirect(w, r, "/p/"+vars["filepath"]+"/", http.StatusFound) diff --git a/gno.land/pkg/keyscli/run.go b/gno.land/pkg/keyscli/run.go index aa0ee298201a..b0e05fe5a84d 100644 --- a/gno.land/pkg/keyscli/run.go +++ b/gno.land/pkg/keyscli/run.go @@ -8,6 +8,7 @@ import ( "os" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/commands" @@ -73,13 +74,13 @@ func execMakeRun(cfg *MakeRunCfg, args []string, cmdio commands.IO) error { return errors.Wrap(err, "parsing gas fee coin") } - memPkg := &std.MemPackage{} + memPkg := &gnovm.MemPackage{} if sourcePath == "-" { // stdin data, err := io.ReadAll(cmdio.In()) if err != nil { return fmt.Errorf("could not read stdin: %w", err) } - memPkg.Files = []*std.MemFile{ + memPkg.Files = []*gnovm.MemFile{ { Name: "stdin.gno", Body: string(data), @@ -97,7 +98,7 @@ func execMakeRun(cfg *MakeRunCfg, args []string, cmdio commands.IO) error { if err != nil { return fmt.Errorf("could not read %q: %w", sourcePath, err) } - memPkg.Files = []*std.MemFile{ + memPkg.Files = []*gnovm.MemFile{ { Name: info.Name(), Body: string(b), diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 53809a7f2231..a199f12898a3 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/gnovm" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/sdk" @@ -149,9 +150,9 @@ func setupAddPkg(success bool) (sdk.Context, sdk.Tx, vmHandler) { env.acck.SetAccount(ctx, acc) env.bank.SetCoins(ctx, addr, std.MustParseCoins(ugnot.ValueString(10000000))) // success message - var files []*std.MemFile + var files []*gnovm.MemFile if success { - files = []*std.MemFile{ + files = []*gnovm.MemFile{ { Name: "hello.gno", Body: `package hello @@ -163,7 +164,7 @@ func Echo() string { } } else { // failed message - files = []*std.MemFile{ + files = []*gnovm.MemFile{ { Name: "hello.gno", Body: `package hello diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index ef1705c7ae9e..7f5216a4f03a 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -14,6 +14,7 @@ import ( "sync" "time" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -832,7 +833,7 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string func (vm *VMKeeper) QueryFile(ctx sdk.Context, filepath string) (res string, err error) { store := vm.newGnoTransactionStore(ctx) // throwaway (never committed) - dirpath, filename := std.SplitFilepath(filepath) + dirpath, filename := gnovm.SplitFilepath(filepath) if filename != "" { memFile := store.GetMemFile(dirpath, filename) if memFile == nil { diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index c6d8e3f5fa07..3aba53d44905 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/db/memdb" @@ -35,7 +36,7 @@ func TestVMKeeperAddPackage(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ { Name: "test.gno", Body: `package test @@ -80,7 +81,7 @@ func TestVMKeeperOrigSend1(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test @@ -125,7 +126,7 @@ func TestVMKeeperOrigSend2(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test @@ -179,7 +180,7 @@ func TestVMKeeperOrigSend3(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test @@ -223,7 +224,7 @@ func TestVMKeeperRealmSend1(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test @@ -267,7 +268,7 @@ func TestVMKeeperRealmSend2(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test @@ -312,7 +313,7 @@ func TestVMKeeperParams(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {"init.gno", ` package test @@ -365,7 +366,7 @@ func TestVMKeeperOrigCallerInit(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test @@ -416,7 +417,7 @@ func TestVMKeeperRunSimple(t *testing.T) { acc := env.acck.NewAccountWithAddress(ctx, addr) env.acck.SetAccount(ctx, acc) - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "script.gno", Body: ` package main @@ -455,7 +456,7 @@ func testVMKeeperRunImportStdlibs(t *testing.T, env testEnv) { acc := env.acck.NewAccountWithAddress(ctx, addr) env.acck.SetAccount(ctx, acc) - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "script.gno", Body: ` package main @@ -488,7 +489,7 @@ func TestNumberOfArgsError(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ { Name: "test.gno", Body: `package test @@ -527,7 +528,7 @@ func TestVMKeeperReinitialize(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ {Name: "init.gno", Body: ` package test diff --git a/gno.land/pkg/sdk/vm/msg_test.go b/gno.land/pkg/sdk/vm/msg_test.go index eaaaa0f0ab22..684dc21e9f2b 100644 --- a/gno.land/pkg/sdk/vm/msg_test.go +++ b/gno.land/pkg/sdk/vm/msg_test.go @@ -3,6 +3,7 @@ package vm import ( "testing" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/stretchr/testify/assert" @@ -14,7 +15,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { creator := crypto.AddressFromPreimage([]byte("addr1")) pkgName := "test" pkgPath := "gno.land/r/namespace/test" - files := []*std.MemFile{ + files := []*gnovm.MemFile{ { Name: "test.gno", Body: `package test @@ -40,7 +41,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { name: "missing creator address", msg: MsgAddPackage{ Creator: crypto.Address{}, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: files, @@ -56,7 +57,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { name: "missing package path", msg: MsgAddPackage{ Creator: creator, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: "", Files: files, @@ -72,7 +73,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { name: "invalid deposit coins", msg: MsgAddPackage{ Creator: creator, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: files, @@ -199,7 +200,7 @@ func TestMsgRun_ValidateBasic(t *testing.T) { caller := crypto.AddressFromPreimage([]byte("addr1")) pkgName := "main" pkgPath := "gno.land/r/" + caller.String() + "/run" - pkgFiles := []*std.MemFile{ + pkgFiles := []*gnovm.MemFile{ { Name: "main.gno", Body: `package main @@ -226,7 +227,7 @@ func TestMsgRun_ValidateBasic(t *testing.T) { name: "invalid caller address", msg: MsgRun{ Caller: crypto.Address{}, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: pkgFiles, @@ -242,7 +243,7 @@ func TestMsgRun_ValidateBasic(t *testing.T) { name: "invalid package path", msg: MsgRun{ Caller: caller, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: "gno.land/r/namespace/test", // this is not a valid run path Files: pkgFiles, diff --git a/gno.land/pkg/sdk/vm/msgs.go b/gno.land/pkg/sdk/vm/msgs.go index d650c23f3825..d5b82067a98d 100644 --- a/gno.land/pkg/sdk/vm/msgs.go +++ b/gno.land/pkg/sdk/vm/msgs.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -16,15 +17,15 @@ import ( // MsgAddPackage - create and initialize new package type MsgAddPackage struct { - Creator crypto.Address `json:"creator" yaml:"creator"` - Package *std.MemPackage `json:"package" yaml:"package"` - Deposit std.Coins `json:"deposit" yaml:"deposit"` + Creator crypto.Address `json:"creator" yaml:"creator"` + Package *gnovm.MemPackage `json:"package" yaml:"package"` + Deposit std.Coins `json:"deposit" yaml:"deposit"` } var _ std.Msg = MsgAddPackage{} // NewMsgAddPackage - upload a package with files. -func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*std.MemFile) MsgAddPackage { +func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*gnovm.MemFile) MsgAddPackage { var pkgName string for _, file := range files { if strings.HasSuffix(file.Name, ".gno") { @@ -34,7 +35,7 @@ func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*std.MemFi } return MsgAddPackage{ Creator: creator, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: files, @@ -145,14 +146,14 @@ func (msg MsgCall) GetReceived() std.Coins { // MsgRun - executes arbitrary Gno code. type MsgRun struct { - Caller crypto.Address `json:"caller" yaml:"caller"` - Send std.Coins `json:"send" yaml:"send"` - Package *std.MemPackage `json:"package" yaml:"package"` + Caller crypto.Address `json:"caller" yaml:"caller"` + Send std.Coins `json:"send" yaml:"send"` + Package *gnovm.MemPackage `json:"package" yaml:"package"` } var _ std.Msg = MsgRun{} -func NewMsgRun(caller crypto.Address, send std.Coins, files []*std.MemFile) MsgRun { +func NewMsgRun(caller crypto.Address, send std.Coins, files []*gnovm.MemFile) MsgRun { for _, file := range files { if strings.HasSuffix(file.Name, ".gno") { pkgName := string(gno.PackageNameFromFileBody(file.Name, file.Body)) @@ -164,7 +165,7 @@ func NewMsgRun(caller crypto.Address, send std.Coins, files []*std.MemFile) MsgR return MsgRun{ Caller: caller, Send: send, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", Path: "", // auto set by the handler Files: files, diff --git a/gno.land/pkg/sdk/vm/package.go b/gno.land/pkg/sdk/vm/package.go index 30dd116d4e39..0359061ccea6 100644 --- a/gno.land/pkg/sdk/vm/package.go +++ b/gno.land/pkg/sdk/vm/package.go @@ -1,6 +1,7 @@ package vm import ( + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -11,6 +12,7 @@ var Package = amino.RegisterPackage(amino.NewPackage( amino.GetCallersDirname(), ).WithDependencies( std.Package, + gnovm.Package, ).WithTypes( MsgCall{}, "m_call", MsgRun{}, "m_run", diff --git a/gno.land/pkg/sdk/vm/vm.proto b/gno.land/pkg/sdk/vm/vm.proto index e02226e1ae49..efaf025e431e 100644 --- a/gno.land/pkg/sdk/vm/vm.proto +++ b/gno.land/pkg/sdk/vm/vm.proto @@ -5,6 +5,7 @@ option go_package = "github.com/gnolang/gno/gno.land/pkg/sdk/vm/pb"; // imports import "github.com/gnolang/gno/tm2/pkg/std/std.proto"; +import "github.com/gnolang/gno/gnovm/gnovm.proto"; // messages message m_call { @@ -18,12 +19,12 @@ message m_call { message m_run { string caller = 1; string send = 2; - std.MemPackage package = 3; + gnovm.MemPackage package = 3; } message m_addpkg { string creator = 1; - std.MemPackage package = 2; + gnovm.MemPackage package = 2; string deposit = 3; } @@ -40,5 +41,8 @@ message InvalidExprError { } message TypeCheckError { - repeated string errors = 1 [json_name = "Errors"]; + repeated string errors = 1; +} + +message UnauthorizedUserError { } \ No newline at end of file diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index e23f9fa27502..c6feebfd2b5e 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -17,6 +17,7 @@ import ( "go.uber.org/multierr" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" @@ -25,7 +26,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/random" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/testutils" ) @@ -324,7 +324,7 @@ func gnoTestPkg( m := tests.TestMachine(testStore, stdout, testPkgName) - memFiles := make([]*std.MemFile, 0, len(ifiles.FileNames())+1) + memFiles := make([]*gnovm.MemFile, 0, len(ifiles.FileNames())+1) for _, f := range memPkg.Files { for _, ifileName := range ifiles.FileNames() { if f.Name == "gno.mod" || f.Name == ifileName { @@ -599,7 +599,7 @@ func loadTestFuncs(pkgName string, t *testFuncs, tfiles *gno.FileSet) *testFuncs // parseMemPackageTests is copied from gno.ParseMemPackageTests // for except to _filetest.gno -func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { +func parseMemPackageTests(memPkg *gnovm.MemPackage) (tset, itset *gno.FileSet) { tset = &gno.FileSet{} itset = &gno.FileSet{} var errs error diff --git a/gnovm/gno.proto b/gnovm/gno.proto index 5f53c363b731..8a15ca96e14b 100644 --- a/gnovm/gno.proto +++ b/gnovm/gno.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package gno; -option go_package = "github.com/gnolang/gno/pb"; +option go_package = "github.com/gnolang/gno/gnovm/pb"; // imports import "google/protobuf/any.proto"; @@ -601,3 +601,15 @@ message tupleType { message RefType { string ID = 1; } + +// messages +message MemFile { + string name = 1; + string body = 2; +} + +message MemPackage { + string name = 1; + string path = 2; + repeated MemFile files = 3; +} diff --git a/gnovm/gnovm.proto b/gnovm/gnovm.proto new file mode 100644 index 000000000000..c9f0b23ae80e --- /dev/null +++ b/gnovm/gnovm.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package gnovm; + +option go_package = "github.com/gnolang/gno/gnovm/pb"; + +// messages +message MemFile { + string name = 1; + string body = 2; +} + +message MemPackage { + string name = 1; + string path = 2; + repeated MemFile files = 3; +} \ No newline at end of file diff --git a/tm2/pkg/std/memfile.go b/gnovm/memfile.go similarity index 99% rename from tm2/pkg/std/memfile.go rename to gnovm/memfile.go index 01bc18c1487d..a37bba6ef3d8 100644 --- a/tm2/pkg/std/memfile.go +++ b/gnovm/memfile.go @@ -1,4 +1,4 @@ -package std +package gnovm import ( "fmt" diff --git a/tm2/pkg/std/memfile_test.go b/gnovm/memfile_test.go similarity index 99% rename from tm2/pkg/std/memfile_test.go rename to gnovm/memfile_test.go index 3e1fb49e131d..c93c251b0e71 100644 --- a/tm2/pkg/std/memfile_test.go +++ b/gnovm/memfile_test.go @@ -1,4 +1,4 @@ -package std +package gnovm import ( "testing" diff --git a/gnovm/package.go b/gnovm/package.go new file mode 100644 index 000000000000..d6332b05709c --- /dev/null +++ b/gnovm/package.go @@ -0,0 +1,15 @@ +package gnovm + +import ( + "github.com/gnolang/gno/tm2/pkg/amino" +) + +var Package = amino.RegisterPackage(amino.NewPackage( + "github.com/gnolang/gno/gnovm", + "gnovm", + amino.GetCallersDirname(), +).WithDependencies().WithTypes( + // MemFile/MemPackage + MemFile{}, "MemFile", + MemPackage{}, "MemPackage", +)) diff --git a/gnovm/pkg/gnolang/gnolang.proto b/gnovm/pkg/gnolang/gnolang.proto index eee9a0375e6c..27c26534a5f1 100644 --- a/gnovm/pkg/gnolang/gnolang.proto +++ b/gnovm/pkg/gnolang/gnolang.proto @@ -56,10 +56,11 @@ message FuncValue { google.protobuf.Any source = 3 [json_name = "Source"]; string name = 4 [json_name = "Name"]; google.protobuf.Any closure = 5 [json_name = "Closure"]; - string file_name = 6 [json_name = "FileName"]; - string pkg_path = 7 [json_name = "PkgPath"]; - string native_pkg = 8 [json_name = "NativePkg"]; - string native_name = 9 [json_name = "NativeName"]; + repeated TypedValue captures = 6 [json_name = "Captures"]; + string file_name = 7 [json_name = "FileName"]; + string pkg_path = 8 [json_name = "PkgPath"]; + string native_pkg = 9 [json_name = "NativePkg"]; + string native_name = 10 [json_name = "NativeName"]; } message MapValue { @@ -110,6 +111,11 @@ message RefValue { string hash = 4 [json_name = "Hash"]; } +message HeapItemValue { + ObjectInfo object_info = 1 [json_name = "ObjectInfo"]; + TypedValue value = 2 [json_name = "Value"]; +} + message ObjectID { string value = 1; } @@ -147,13 +153,15 @@ message Location { message Attributes { sint64 line = 1 [json_name = "Line"]; - string label = 2 [json_name = "Label"]; + sint64 column = 2 [json_name = "Column"]; + string label = 3 [json_name = "Label"]; } message NameExpr { Attributes attributes = 1 [json_name = "Attributes"]; ValuePath path = 2 [json_name = "Path"]; string name = 3 [json_name = "Name"]; + sint64 type = 4 [json_name = "Type"]; } message BasicLitExpr { @@ -239,6 +247,7 @@ message FuncLitExpr { StaticBlock static_block = 2 [json_name = "StaticBlock"]; FuncTypeExpr type = 3 [json_name = "Type"]; repeated google.protobuf.Any body = 4 [json_name = "Body"]; + repeated NameExpr heap_captures = 5 [json_name = "HeapCaptures"]; } message ConstExpr { @@ -602,4 +611,4 @@ message tupleType { message RefType { string id = 1 [json_name = "ID"]; -} +} \ No newline at end of file diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index 6bde6fb5271e..99e051f79136 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -44,8 +44,8 @@ import ( "strings" "github.com/davecgh/go-spew/spew" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" ) @@ -486,7 +486,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { // MemPackageGetter implements the GetMemPackage() method. It is a subset of // [Store], separated for ease of testing. type MemPackageGetter interface { - GetMemPackage(path string) *std.MemPackage + GetMemPackage(path string) *gnovm.MemPackage } // TypeCheckMemPackage performs type validation and checking on the given @@ -496,7 +496,7 @@ type MemPackageGetter interface { // // If format is true, the code will be automatically updated with the // formatted source code. -func TypeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, format bool) error { +func TypeCheckMemPackage(mempkg *gnovm.MemPackage, getter MemPackageGetter, format bool) error { var errs error imp := &gnoImporter{ getter: getter, @@ -556,7 +556,7 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac return result, err } -func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt bool) (*types.Package, error) { +func (g *gnoImporter) parseCheckMemPackage(mpkg *gnovm.MemPackage, fmt bool) (*types.Package, error) { fset := token.NewFileSet() files := make([]*ast.File, 0, len(mpkg.Files)) var errs error diff --git a/gnovm/pkg/gnolang/go2gno_test.go b/gnovm/pkg/gnolang/go2gno_test.go index d85c142ca524..8aba5d7f2937 100644 --- a/gnovm/pkg/gnolang/go2gno_test.go +++ b/gnovm/pkg/gnolang/go2gno_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/gnolang/gno/tm2/pkg/std" + "github.com/gnolang/gno/gnovm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/multierr" @@ -29,9 +29,9 @@ func main(){ fmt.Printf("AST.String():\n%s\n", n.String()) } -type mockPackageGetter []*std.MemPackage +type mockPackageGetter []*gnovm.MemPackage -func (mi mockPackageGetter) GetMemPackage(path string) *std.MemPackage { +func (mi mockPackageGetter) GetMemPackage(path string) *gnovm.MemPackage { for _, pkg := range mi { if pkg.Path == path { return pkg @@ -45,7 +45,7 @@ type mockPackageGetterCounts struct { counts map[string]int } -func (mpg mockPackageGetterCounts) GetMemPackage(path string) *std.MemPackage { +func (mpg mockPackageGetterCounts) GetMemPackage(path string) *gnovm.MemPackage { mpg.counts[path]++ return mpg.mockPackageGetter.GetMemPackage(path) } @@ -77,17 +77,17 @@ func TestTypeCheckMemPackage(t *testing.T) { type testCase struct { name string - pkg *std.MemPackage + pkg *gnovm.MemPackage getter MemPackageGetter check func(*testing.T, error) } tt := []testCase{ { "Simple", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -103,10 +103,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "WrongReturn", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -122,10 +122,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ParseError", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -139,10 +139,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "MultiError", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "main", Path: "gno.land/p/demo/main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -159,10 +159,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "TestsIgnored", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -181,10 +181,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ImportFailed", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -199,10 +199,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ImportSucceeded", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -213,12 +213,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, mockPackageGetter{ - &std.MemPackage{ + &gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { - Name: "std.gno", + Name: "gnovm.gno", Body: ` package std type Address string`, @@ -230,10 +230,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ImportBadIdent", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -244,12 +244,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, mockPackageGetter{ - &std.MemPackage{ + &gnovm.MemPackage{ Name: "a_completely_different_identifier", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { - Name: "std.gno", + Name: "gnovm.gno", Body: ` package a_completely_different_identifier type Address string`, @@ -263,10 +263,10 @@ func TestTypeCheckMemPackage(t *testing.T) { cacheMpg := mockPackageGetterCounts{ mockPackageGetter{ - &std.MemPackage{ + &gnovm.MemPackage{ Name: "bye", Path: "bye", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "bye.gno", Body: ` @@ -276,12 +276,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, }, - &std.MemPackage{ + &gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { - Name: "std.gno", + Name: "gnovm.gno", Body: ` package std type Address string`, @@ -295,10 +295,10 @@ func TestTypeCheckMemPackage(t *testing.T) { tt = append(tt, testCase{ "ImportWithCache", // This test will make use of the importer's internal cache for package `std`. - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -347,10 +347,10 @@ func TestTypeCheckMemPackage_format(t *testing.T) { ` - pkg := &std.MemPackage{ + pkg := &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: input, diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 1e594de945bd..09be71682a52 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -16,8 +16,8 @@ import ( "github.com/gnolang/overflow" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" ) @@ -265,7 +265,7 @@ func (m *Machine) PreprocessAllFilesAndSaveBlockNodes() { // Parses files, sets the package if doesn't exist, runs files, saves mempkg // and corresponding package node, package value, and types to store. Save // is set to false for tests where package values may be native. -func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { +func (m *Machine) RunMemPackage(memPkg *gnovm.MemPackage, save bool) (*PackageNode, *PackageValue) { return m.runMemPackage(memPkg, save, false) } @@ -273,11 +273,11 @@ func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode // declarations are filtered removing duplicate declarations. // To control which declaration overrides which, use [ReadMemPackageFromList], // putting the overrides at the top of the list. -func (m *Machine) RunMemPackageWithOverrides(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { +func (m *Machine) RunMemPackageWithOverrides(memPkg *gnovm.MemPackage, save bool) (*PackageNode, *PackageValue) { return m.runMemPackage(memPkg, save, true) } -func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (*PackageNode, *PackageValue) { +func (m *Machine) runMemPackage(memPkg *gnovm.MemPackage, save, overrides bool) (*PackageNode, *PackageValue) { // parse files. files := ParseMemPackage(memPkg) if !overrides { @@ -406,7 +406,7 @@ func destar(x Expr) Expr { // The resulting package value and node become injected with TestMethods and // other declarations, so it is expected that non-test code will not be run // afterwards from the same store. -func (m *Machine) TestMemPackage(t *testing.T, memPkg *std.MemPackage) { +func (m *Machine) TestMemPackage(t *testing.T, memPkg *gnovm.MemPackage) { defer m.injectLocOnPanic() DisableDebug() fmt.Println("DEBUG DISABLED (FOR TEST DEPENDENCIES INIT)") diff --git a/gnovm/pkg/gnolang/machine_test.go b/gnovm/pkg/gnolang/machine_test.go index 8e27b127fbbd..c3b2118f099b 100644 --- a/gnovm/pkg/gnolang/machine_test.go +++ b/gnovm/pkg/gnolang/machine_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/db/memdb" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" "github.com/gnolang/gno/tm2/pkg/store/iavl" stypes "github.com/gnolang/gno/tm2/pkg/store/types" @@ -27,10 +27,10 @@ func TestRunMemPackageWithOverrides_revertToOld(t *testing.T) { iavlStore := iavl.StoreConstructor(db, stypes.StoreOptions{}) store := NewStore(nil, baseStore, iavlStore) m := NewMachine("std", store) - m.RunMemPackageWithOverrides(&std.MemPackage{ + m.RunMemPackageWithOverrides(&gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "a.gno", Body: `package std; func Redecl(x int) string { return "1" }`}, }, }, true) @@ -38,10 +38,10 @@ func TestRunMemPackageWithOverrides_revertToOld(t *testing.T) { defer func() { p = fmt.Sprint(recover()) }() - m.RunMemPackageWithOverrides(&std.MemPackage{ + m.RunMemPackageWithOverrides(&gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "b.gno", Body: `package std; func Redecl(x int) string { var y string; _, _ = y; return "2" }`}, }, }, true) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 9e7cea8fb7f3..c282b619fdcb 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -12,8 +12,8 @@ import ( "strconv" "strings" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" ) @@ -1152,7 +1152,7 @@ func PackageNameFromFileBody(name, body string) Name { // // NOTE: panics if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). -func ReadMemPackage(dir string, pkgPath string) *std.MemPackage { +func ReadMemPackage(dir string, pkgPath string) *gnovm.MemPackage { files, err := os.ReadDir(dir) if err != nil { panic(err) @@ -1186,14 +1186,14 @@ func ReadMemPackage(dir string, pkgPath string) *std.MemPackage { return ReadMemPackageFromList(list, pkgPath) } -// ReadMemPackageFromList creates a new [std.MemPackage] with the specified pkgPath, +// ReadMemPackageFromList creates a new [gnovm.MemPackage] with the specified pkgPath, // containing the contents of all the files provided in the list slice. // No parsing or validation is done on the filenames. // // NOTE: panics if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). -func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { - memPkg := &std.MemPackage{Path: pkgPath} +func ReadMemPackageFromList(list []string, pkgPath string) *gnovm.MemPackage { + memPkg := &gnovm.MemPackage{Path: pkgPath} var pkgName Name for _, fpath := range list { fname := filepath.Base(fpath) @@ -1209,7 +1209,7 @@ func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { } } memPkg.Files = append(memPkg.Files, - &std.MemFile{ + &gnovm.MemFile{ Name: fname, Body: string(bz), }) @@ -1229,7 +1229,7 @@ func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { // // If one of the files has a different package name than memPkg.Name, // or [ParseFile] returns an error, ParseMemPackage panics. -func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { +func ParseMemPackage(memPkg *gnovm.MemPackage) (fset *FileSet) { fset = &FileSet{} var errs error for _, mfile := range memPkg.Files { @@ -1256,7 +1256,7 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { return fset } -func ParseMemPackageTests(memPkg *std.MemPackage) (tset, itset *FileSet) { +func ParseMemPackageTests(memPkg *gnovm.MemPackage) (tset, itset *FileSet) { tset = &FileSet{} itset = &FileSet{} for _, mfile := range memPkg.Files { diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index 9913c434282b..dfb1e9f114c4 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -7,10 +7,10 @@ import ( "strconv" "strings" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnolang/internal/txlog" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/colors" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/utils" stringz "github.com/gnolang/gno/tm2/pkg/strings" @@ -58,10 +58,10 @@ type Store interface { // Upon restart, all packages will be re-preprocessed; This // loads BlockNodes and Types onto the store for persistence // version 1. - AddMemPackage(memPkg *std.MemPackage) - GetMemPackage(path string) *std.MemPackage - GetMemFile(path string, name string) *std.MemFile - IterMemPackage() <-chan *std.MemPackage + AddMemPackage(memPkg *gnovm.MemPackage) + GetMemPackage(path string) *gnovm.MemPackage + GetMemFile(path string, name string) *gnovm.MemFile + IterMemPackage() <-chan *gnovm.MemPackage ClearObjectCache() // run before processing a message SetNativeStore(NativeStore) // for "new" natives XXX GetNative(pkgPath string, name Name) func(m *Machine) // for "new" natives XXX @@ -611,7 +611,7 @@ func (ds *defaultStore) incGetPackageIndexCounter() uint64 { } } -func (ds *defaultStore) AddMemPackage(memPkg *std.MemPackage) { +func (ds *defaultStore) AddMemPackage(memPkg *gnovm.MemPackage) { memPkg.Validate() // NOTE: duplicate validation. ctr := ds.incGetPackageIndexCounter() idxkey := []byte(backendPackageIndexKey(ctr)) @@ -623,11 +623,11 @@ func (ds *defaultStore) AddMemPackage(memPkg *std.MemPackage) { // GetMemPackage retrieves the MemPackage at the given path. // It returns nil if the package could not be found. -func (ds *defaultStore) GetMemPackage(path string) *std.MemPackage { +func (ds *defaultStore) GetMemPackage(path string) *gnovm.MemPackage { return ds.getMemPackage(path, false) } -func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage { +func (ds *defaultStore) getMemPackage(path string, isRetry bool) *gnovm.MemPackage { pathkey := []byte(backendPackagePathKey(path)) bz := ds.iavlStore.Get(pathkey) if bz == nil { @@ -644,7 +644,7 @@ func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage return nil } - var memPkg *std.MemPackage + var memPkg *gnovm.MemPackage amino.MustUnmarshal(bz, &memPkg) return memPkg } @@ -652,7 +652,7 @@ func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage // GetMemFile retrieves the MemFile with the given name, contained in the // MemPackage at the given path. It returns nil if the file or the package // do not exist. -func (ds *defaultStore) GetMemFile(path string, name string) *std.MemFile { +func (ds *defaultStore) GetMemFile(path string, name string) *gnovm.MemFile { memPkg := ds.GetMemPackage(path) if memPkg == nil { return nil @@ -661,7 +661,7 @@ func (ds *defaultStore) GetMemFile(path string, name string) *std.MemFile { return memFile } -func (ds *defaultStore) IterMemPackage() <-chan *std.MemPackage { +func (ds *defaultStore) IterMemPackage() <-chan *gnovm.MemPackage { ctrkey := []byte(backendPackageIndexCtrKey()) ctrbz := ds.baseStore.Get(ctrkey) if ctrbz == nil { @@ -671,7 +671,7 @@ func (ds *defaultStore) IterMemPackage() <-chan *std.MemPackage { if err != nil { panic(err) } - ch := make(chan *std.MemPackage, 0) + ch := make(chan *gnovm.MemPackage, 0) go func() { for i := uint64(1); i <= uint64(ctr); i++ { idxkey := []byte(backendPackageIndexKey(i)) diff --git a/gnovm/pkg/gnolang/store_test.go b/gnovm/pkg/gnolang/store_test.go index 17f55993705f..40f84b65375b 100644 --- a/gnovm/pkg/gnolang/store_test.go +++ b/gnovm/pkg/gnolang/store_test.go @@ -4,8 +4,8 @@ import ( "io" "testing" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/db/memdb" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" storetypes "github.com/gnolang/gno/tm2/pkg/store/types" "github.com/stretchr/testify/assert" @@ -23,10 +23,10 @@ func TestTransactionStore(t *testing.T) { Store: txSt, Output: io.Discard, }) - _, pv := m.RunMemPackage(&std.MemPackage{ + _, pv := m.RunMemPackage(&gnovm.MemPackage{ Name: "hello", Path: "hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "hello.gno", Body: "package hello; func main() { println(A(11)); }; type A int"}, }, }, true) @@ -75,10 +75,10 @@ func TestCopyFromCachedStore(t *testing.T) { Name: "Reader", Base: BoolType, }) - cachedStore.AddMemPackage(&std.MemPackage{ + cachedStore.AddMemPackage(&gnovm.MemPackage{ Name: "math", Path: "math", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "math.gno", Body: "package math"}, }, }) diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 0effa532107c..553bb32f4b54 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -9,10 +9,10 @@ import ( "path/filepath" "strings" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/transpiler" - "github.com/gnolang/gno/tm2/pkg/std" "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) @@ -43,7 +43,7 @@ func writePackage(remote, basePath, pkgPath string) (requirements []string, err return nil, fmt.Errorf("querychain (%s): %w", pkgPath, err) } - dirPath, fileName := std.SplitFilepath(pkgPath) + dirPath, fileName := gnovm.SplitFilepath(pkgPath) if fileName == "" { // Is Dir // Create Dir if not exists diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 5449adc01d25..9df982d4fd81 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -15,6 +15,7 @@ import ( "strings" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" @@ -200,10 +201,10 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { store.SetStrictGo2GnoMapping(true) // in gno.land, natives must be registered. gno.DisableDebug() // until main call. // save package using realm crawl procedure. - memPkg := &std.MemPackage{ + memPkg := &gnovm.MemPackage{ Name: string(pkgName), Path: pkgPath, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", // dontcare Body: string(bz), diff --git a/misc/genproto/Makefile b/misc/genproto/Makefile index 1033a1b2b248..8c4bfc3118bc 100644 --- a/misc/genproto/Makefile +++ b/misc/genproto/Makefile @@ -9,3 +9,7 @@ all: --go_opt=Mproto/compat.proto=github.com/gnolang/gno/tm2/pkg/amino/tests/proto3 \ --go-grpc_opt=Mproto/compat.proto=github.com/gnolang/gno/tm2/pkg/amino/tests/proto3 \ --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/compat.proto + +deps: + go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest diff --git a/misc/genproto/genproto.go b/misc/genproto/genproto.go index b9b97efbe37f..c1dfd75ce40d 100644 --- a/misc/genproto/genproto.go +++ b/misc/genproto/genproto.go @@ -11,6 +11,7 @@ import ( // TODO: move these out. "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/blockchain" @@ -54,6 +55,7 @@ func execGen(_ context.Context, _ []string) error { hd.Package, multisig.Package, std.Package, + gnovm.Package, sdk.Package, bank.Package, vm.Package, diff --git a/tm2/pkg/amino/tests/pb/tests.pb.go b/tm2/pkg/amino/tests/pb/tests.pb.go deleted file mode 100644 index 6776f5ecb575..000000000000 --- a/tm2/pkg/amino/tests/pb/tests.pb.go +++ /dev/null @@ -1,5582 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.3 -// source: tests.proto - -package pb - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - durationpb "google.golang.org/protobuf/types/known/durationpb" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// messages -type EmptyStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *EmptyStruct) Reset() { - *x = EmptyStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmptyStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmptyStruct) ProtoMessage() {} - -func (x *EmptyStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmptyStruct.ProtoReflect.Descriptor instead. -func (*EmptyStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{0} -} - -type PrimitivesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8 int32 `protobuf:"zigzag32,1,opt,name=int8,json=Int8,proto3" json:"int8,omitempty"` - Int16 int32 `protobuf:"zigzag32,2,opt,name=int16,json=Int16,proto3" json:"int16,omitempty"` - Int32 int32 `protobuf:"zigzag32,3,opt,name=int32,json=Int32,proto3" json:"int32,omitempty"` - Int32Fixed int32 `protobuf:"fixed32,4,opt,name=int32_fixed,json=Int32Fixed,proto3" json:"int32_fixed,omitempty"` - Int64 int64 `protobuf:"zigzag64,5,opt,name=int64,json=Int64,proto3" json:"int64,omitempty"` - Int64Fixed int64 `protobuf:"fixed64,6,opt,name=int64_fixed,json=Int64Fixed,proto3" json:"int64_fixed,omitempty"` - Int int64 `protobuf:"zigzag64,7,opt,name=int,json=Int,proto3" json:"int,omitempty"` - Byte uint32 `protobuf:"varint,8,opt,name=byte,json=Byte,proto3" json:"byte,omitempty"` - Uint8 uint32 `protobuf:"varint,9,opt,name=uint8,json=Uint8,proto3" json:"uint8,omitempty"` - Uint16 uint32 `protobuf:"varint,10,opt,name=uint16,json=Uint16,proto3" json:"uint16,omitempty"` - Uint32 uint32 `protobuf:"varint,11,opt,name=uint32,json=Uint32,proto3" json:"uint32,omitempty"` - Uint32Fixed uint32 `protobuf:"fixed32,12,opt,name=uint32_fixed,json=Uint32Fixed,proto3" json:"uint32_fixed,omitempty"` - Uint64 uint64 `protobuf:"varint,13,opt,name=uint64,json=Uint64,proto3" json:"uint64,omitempty"` - Uint64Fixed uint64 `protobuf:"fixed64,14,opt,name=uint64_fixed,json=Uint64Fixed,proto3" json:"uint64_fixed,omitempty"` - Uint uint64 `protobuf:"varint,15,opt,name=uint,json=Uint,proto3" json:"uint,omitempty"` - Str string `protobuf:"bytes,16,opt,name=str,json=Str,proto3" json:"str,omitempty"` - Bytes []byte `protobuf:"bytes,17,opt,name=bytes,json=Bytes,proto3" json:"bytes,omitempty"` - Time *timestamppb.Timestamp `protobuf:"bytes,18,opt,name=time,json=Time,proto3" json:"time,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,19,opt,name=duration,json=Duration,proto3" json:"duration,omitempty"` - Empty *EmptyStruct `protobuf:"bytes,20,opt,name=empty,json=Empty,proto3" json:"empty,omitempty"` -} - -func (x *PrimitivesStruct) Reset() { - *x = PrimitivesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStruct) ProtoMessage() {} - -func (x *PrimitivesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStruct.ProtoReflect.Descriptor instead. -func (*PrimitivesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{1} -} - -func (x *PrimitivesStruct) GetInt8() int32 { - if x != nil { - return x.Int8 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt16() int32 { - if x != nil { - return x.Int16 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt32Fixed() int32 { - if x != nil { - return x.Int32Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt64Fixed() int64 { - if x != nil { - return x.Int64Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetInt() int64 { - if x != nil { - return x.Int - } - return 0 -} - -func (x *PrimitivesStruct) GetByte() uint32 { - if x != nil { - return x.Byte - } - return 0 -} - -func (x *PrimitivesStruct) GetUint8() uint32 { - if x != nil { - return x.Uint8 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint16() uint32 { - if x != nil { - return x.Uint16 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint32() uint32 { - if x != nil { - return x.Uint32 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint32Fixed() uint32 { - if x != nil { - return x.Uint32Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetUint64() uint64 { - if x != nil { - return x.Uint64 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint64Fixed() uint64 { - if x != nil { - return x.Uint64Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetUint() uint64 { - if x != nil { - return x.Uint - } - return 0 -} - -func (x *PrimitivesStruct) GetStr() string { - if x != nil { - return x.Str - } - return "" -} - -func (x *PrimitivesStruct) GetBytes() []byte { - if x != nil { - return x.Bytes - } - return nil -} - -func (x *PrimitivesStruct) GetTime() *timestamppb.Timestamp { - if x != nil { - return x.Time - } - return nil -} - -func (x *PrimitivesStruct) GetDuration() *durationpb.Duration { - if x != nil { - return x.Duration - } - return nil -} - -func (x *PrimitivesStruct) GetEmpty() *EmptyStruct { - if x != nil { - return x.Empty - } - return nil -} - -type ShortArraysStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TimeAr []*timestamppb.Timestamp `protobuf:"bytes,1,rep,name=time_ar,json=TimeAr,proto3" json:"time_ar,omitempty"` - DurationAr []*durationpb.Duration `protobuf:"bytes,2,rep,name=duration_ar,json=DurationAr,proto3" json:"duration_ar,omitempty"` -} - -func (x *ShortArraysStruct) Reset() { - *x = ShortArraysStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShortArraysStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShortArraysStruct) ProtoMessage() {} - -func (x *ShortArraysStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShortArraysStruct.ProtoReflect.Descriptor instead. -func (*ShortArraysStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{2} -} - -func (x *ShortArraysStruct) GetTimeAr() []*timestamppb.Timestamp { - if x != nil { - return x.TimeAr - } - return nil -} - -func (x *ShortArraysStruct) GetDurationAr() []*durationpb.Duration { - if x != nil { - return x.DurationAr - } - return nil -} - -type ArraysStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8Ar []int32 `protobuf:"zigzag32,1,rep,packed,name=int8_ar,json=Int8Ar,proto3" json:"int8_ar,omitempty"` - Int16Ar []int32 `protobuf:"zigzag32,2,rep,packed,name=int16_ar,json=Int16Ar,proto3" json:"int16_ar,omitempty"` - Int32Ar []int32 `protobuf:"zigzag32,3,rep,packed,name=int32_ar,json=Int32Ar,proto3" json:"int32_ar,omitempty"` - Int32FixedAr []int32 `protobuf:"fixed32,4,rep,packed,name=int32_fixed_ar,json=Int32FixedAr,proto3" json:"int32_fixed_ar,omitempty"` - Int64Ar []int64 `protobuf:"zigzag64,5,rep,packed,name=int64_ar,json=Int64Ar,proto3" json:"int64_ar,omitempty"` - Int64FixedAr []int64 `protobuf:"fixed64,6,rep,packed,name=int64_fixed_ar,json=Int64FixedAr,proto3" json:"int64_fixed_ar,omitempty"` - IntAr []int64 `protobuf:"zigzag64,7,rep,packed,name=int_ar,json=IntAr,proto3" json:"int_ar,omitempty"` - ByteAr []byte `protobuf:"bytes,8,opt,name=byte_ar,json=ByteAr,proto3" json:"byte_ar,omitempty"` - Uint8Ar []byte `protobuf:"bytes,9,opt,name=uint8_ar,json=Uint8Ar,proto3" json:"uint8_ar,omitempty"` - Uint16Ar []uint32 `protobuf:"varint,10,rep,packed,name=uint16_ar,json=Uint16Ar,proto3" json:"uint16_ar,omitempty"` - Uint32Ar []uint32 `protobuf:"varint,11,rep,packed,name=uint32_ar,json=Uint32Ar,proto3" json:"uint32_ar,omitempty"` - Uint32FixedAr []uint32 `protobuf:"fixed32,12,rep,packed,name=uint32_fixed_ar,json=Uint32FixedAr,proto3" json:"uint32_fixed_ar,omitempty"` - Uint64Ar []uint64 `protobuf:"varint,13,rep,packed,name=uint64_ar,json=Uint64Ar,proto3" json:"uint64_ar,omitempty"` - Uint64FixedAr []uint64 `protobuf:"fixed64,14,rep,packed,name=uint64_fixed_ar,json=Uint64FixedAr,proto3" json:"uint64_fixed_ar,omitempty"` - UintAr []uint64 `protobuf:"varint,15,rep,packed,name=uint_ar,json=UintAr,proto3" json:"uint_ar,omitempty"` - StrAr []string `protobuf:"bytes,16,rep,name=str_ar,json=StrAr,proto3" json:"str_ar,omitempty"` - BytesAr [][]byte `protobuf:"bytes,17,rep,name=bytes_ar,json=BytesAr,proto3" json:"bytes_ar,omitempty"` - TimeAr []*timestamppb.Timestamp `protobuf:"bytes,18,rep,name=time_ar,json=TimeAr,proto3" json:"time_ar,omitempty"` - DurationAr []*durationpb.Duration `protobuf:"bytes,19,rep,name=duration_ar,json=DurationAr,proto3" json:"duration_ar,omitempty"` - EmptyAr []*EmptyStruct `protobuf:"bytes,20,rep,name=empty_ar,json=EmptyAr,proto3" json:"empty_ar,omitempty"` -} - -func (x *ArraysStruct) Reset() { - *x = ArraysStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ArraysStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArraysStruct) ProtoMessage() {} - -func (x *ArraysStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArraysStruct.ProtoReflect.Descriptor instead. -func (*ArraysStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{3} -} - -func (x *ArraysStruct) GetInt8Ar() []int32 { - if x != nil { - return x.Int8Ar - } - return nil -} - -func (x *ArraysStruct) GetInt16Ar() []int32 { - if x != nil { - return x.Int16Ar - } - return nil -} - -func (x *ArraysStruct) GetInt32Ar() []int32 { - if x != nil { - return x.Int32Ar - } - return nil -} - -func (x *ArraysStruct) GetInt32FixedAr() []int32 { - if x != nil { - return x.Int32FixedAr - } - return nil -} - -func (x *ArraysStruct) GetInt64Ar() []int64 { - if x != nil { - return x.Int64Ar - } - return nil -} - -func (x *ArraysStruct) GetInt64FixedAr() []int64 { - if x != nil { - return x.Int64FixedAr - } - return nil -} - -func (x *ArraysStruct) GetIntAr() []int64 { - if x != nil { - return x.IntAr - } - return nil -} - -func (x *ArraysStruct) GetByteAr() []byte { - if x != nil { - return x.ByteAr - } - return nil -} - -func (x *ArraysStruct) GetUint8Ar() []byte { - if x != nil { - return x.Uint8Ar - } - return nil -} - -func (x *ArraysStruct) GetUint16Ar() []uint32 { - if x != nil { - return x.Uint16Ar - } - return nil -} - -func (x *ArraysStruct) GetUint32Ar() []uint32 { - if x != nil { - return x.Uint32Ar - } - return nil -} - -func (x *ArraysStruct) GetUint32FixedAr() []uint32 { - if x != nil { - return x.Uint32FixedAr - } - return nil -} - -func (x *ArraysStruct) GetUint64Ar() []uint64 { - if x != nil { - return x.Uint64Ar - } - return nil -} - -func (x *ArraysStruct) GetUint64FixedAr() []uint64 { - if x != nil { - return x.Uint64FixedAr - } - return nil -} - -func (x *ArraysStruct) GetUintAr() []uint64 { - if x != nil { - return x.UintAr - } - return nil -} - -func (x *ArraysStruct) GetStrAr() []string { - if x != nil { - return x.StrAr - } - return nil -} - -func (x *ArraysStruct) GetBytesAr() [][]byte { - if x != nil { - return x.BytesAr - } - return nil -} - -func (x *ArraysStruct) GetTimeAr() []*timestamppb.Timestamp { - if x != nil { - return x.TimeAr - } - return nil -} - -func (x *ArraysStruct) GetDurationAr() []*durationpb.Duration { - if x != nil { - return x.DurationAr - } - return nil -} - -func (x *ArraysStruct) GetEmptyAr() []*EmptyStruct { - if x != nil { - return x.EmptyAr - } - return nil -} - -type ArraysArraysStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8ArAr []*TESTS_Int8List `protobuf:"bytes,1,rep,name=int8_ar_ar,json=Int8ArAr,proto3" json:"int8_ar_ar,omitempty"` - Int16ArAr []*TESTS_Int16List `protobuf:"bytes,2,rep,name=int16_ar_ar,json=Int16ArAr,proto3" json:"int16_ar_ar,omitempty"` - Int32ArAr []*TESTS_Int32ValueList `protobuf:"bytes,3,rep,name=int32_ar_ar,json=Int32ArAr,proto3" json:"int32_ar_ar,omitempty"` - Int32FixedArAr []*TESTS_Fixed32Int32ValueList `protobuf:"bytes,4,rep,name=int32_fixed_ar_ar,json=Int32FixedArAr,proto3" json:"int32_fixed_ar_ar,omitempty"` - Int64ArAr []*TESTS_Int64ValueList `protobuf:"bytes,5,rep,name=int64_ar_ar,json=Int64ArAr,proto3" json:"int64_ar_ar,omitempty"` - Int64FixedArAr []*TESTS_Fixed64Int64ValueList `protobuf:"bytes,6,rep,name=int64_fixed_ar_ar,json=Int64FixedArAr,proto3" json:"int64_fixed_ar_ar,omitempty"` - IntArAr []*TESTS_Int64ValueList `protobuf:"bytes,7,rep,name=int_ar_ar,json=IntArAr,proto3" json:"int_ar_ar,omitempty"` - ByteArAr [][]byte `protobuf:"bytes,8,rep,name=byte_ar_ar,json=ByteArAr,proto3" json:"byte_ar_ar,omitempty"` - Uint8ArAr [][]byte `protobuf:"bytes,9,rep,name=uint8_ar_ar,json=Uint8ArAr,proto3" json:"uint8_ar_ar,omitempty"` - Uint16ArAr []*TESTS_UInt16List `protobuf:"bytes,10,rep,name=uint16_ar_ar,json=Uint16ArAr,proto3" json:"uint16_ar_ar,omitempty"` - Uint32ArAr []*TESTS_UInt32ValueList `protobuf:"bytes,11,rep,name=uint32_ar_ar,json=Uint32ArAr,proto3" json:"uint32_ar_ar,omitempty"` - Uint32FixedArAr []*TESTS_Fixed32UInt32ValueList `protobuf:"bytes,12,rep,name=uint32_fixed_ar_ar,json=Uint32FixedArAr,proto3" json:"uint32_fixed_ar_ar,omitempty"` - Uint64ArAr []*TESTS_UInt64ValueList `protobuf:"bytes,13,rep,name=uint64_ar_ar,json=Uint64ArAr,proto3" json:"uint64_ar_ar,omitempty"` - Uint64FixedArAr []*TESTS_Fixed64UInt64ValueList `protobuf:"bytes,14,rep,name=uint64_fixed_ar_ar,json=Uint64FixedArAr,proto3" json:"uint64_fixed_ar_ar,omitempty"` - UintArAr []*TESTS_UInt64ValueList `protobuf:"bytes,15,rep,name=uint_ar_ar,json=UintArAr,proto3" json:"uint_ar_ar,omitempty"` - StrArAr []*TESTS_StringValueList `protobuf:"bytes,16,rep,name=str_ar_ar,json=StrArAr,proto3" json:"str_ar_ar,omitempty"` - BytesArAr []*TESTS_BytesList `protobuf:"bytes,17,rep,name=bytes_ar_ar,json=BytesArAr,proto3" json:"bytes_ar_ar,omitempty"` - TimeArAr []*TESTS_TimestampList `protobuf:"bytes,18,rep,name=time_ar_ar,json=TimeArAr,proto3" json:"time_ar_ar,omitempty"` - DurationArAr []*TESTS_DurationList `protobuf:"bytes,19,rep,name=duration_ar_ar,json=DurationArAr,proto3" json:"duration_ar_ar,omitempty"` - EmptyArAr []*TESTS_EmptyStructList `protobuf:"bytes,20,rep,name=empty_ar_ar,json=EmptyArAr,proto3" json:"empty_ar_ar,omitempty"` -} - -func (x *ArraysArraysStruct) Reset() { - *x = ArraysArraysStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ArraysArraysStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArraysArraysStruct) ProtoMessage() {} - -func (x *ArraysArraysStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArraysArraysStruct.ProtoReflect.Descriptor instead. -func (*ArraysArraysStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{4} -} - -func (x *ArraysArraysStruct) GetInt8ArAr() []*TESTS_Int8List { - if x != nil { - return x.Int8ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt16ArAr() []*TESTS_Int16List { - if x != nil { - return x.Int16ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt32ArAr() []*TESTS_Int32ValueList { - if x != nil { - return x.Int32ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt32FixedArAr() []*TESTS_Fixed32Int32ValueList { - if x != nil { - return x.Int32FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt64ArAr() []*TESTS_Int64ValueList { - if x != nil { - return x.Int64ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt64FixedArAr() []*TESTS_Fixed64Int64ValueList { - if x != nil { - return x.Int64FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetIntArAr() []*TESTS_Int64ValueList { - if x != nil { - return x.IntArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetByteArAr() [][]byte { - if x != nil { - return x.ByteArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint8ArAr() [][]byte { - if x != nil { - return x.Uint8ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint16ArAr() []*TESTS_UInt16List { - if x != nil { - return x.Uint16ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint32ArAr() []*TESTS_UInt32ValueList { - if x != nil { - return x.Uint32ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint32FixedArAr() []*TESTS_Fixed32UInt32ValueList { - if x != nil { - return x.Uint32FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint64ArAr() []*TESTS_UInt64ValueList { - if x != nil { - return x.Uint64ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint64FixedArAr() []*TESTS_Fixed64UInt64ValueList { - if x != nil { - return x.Uint64FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUintArAr() []*TESTS_UInt64ValueList { - if x != nil { - return x.UintArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetStrArAr() []*TESTS_StringValueList { - if x != nil { - return x.StrArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetBytesArAr() []*TESTS_BytesList { - if x != nil { - return x.BytesArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetTimeArAr() []*TESTS_TimestampList { - if x != nil { - return x.TimeArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetDurationArAr() []*TESTS_DurationList { - if x != nil { - return x.DurationArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetEmptyArAr() []*TESTS_EmptyStructList { - if x != nil { - return x.EmptyArAr - } - return nil -} - -type SlicesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8Sl []int32 `protobuf:"zigzag32,1,rep,packed,name=int8_sl,json=Int8Sl,proto3" json:"int8_sl,omitempty"` - Int16Sl []int32 `protobuf:"zigzag32,2,rep,packed,name=int16_sl,json=Int16Sl,proto3" json:"int16_sl,omitempty"` - Int32Sl []int32 `protobuf:"zigzag32,3,rep,packed,name=int32_sl,json=Int32Sl,proto3" json:"int32_sl,omitempty"` - Int32FixedSl []int32 `protobuf:"fixed32,4,rep,packed,name=int32_fixed_sl,json=Int32FixedSl,proto3" json:"int32_fixed_sl,omitempty"` - Int64Sl []int64 `protobuf:"zigzag64,5,rep,packed,name=int64_sl,json=Int64Sl,proto3" json:"int64_sl,omitempty"` - Int64FixedSl []int64 `protobuf:"fixed64,6,rep,packed,name=int64_fixed_sl,json=Int64FixedSl,proto3" json:"int64_fixed_sl,omitempty"` - IntSl []int64 `protobuf:"zigzag64,7,rep,packed,name=int_sl,json=IntSl,proto3" json:"int_sl,omitempty"` - ByteSl []byte `protobuf:"bytes,8,opt,name=byte_sl,json=ByteSl,proto3" json:"byte_sl,omitempty"` - Uint8Sl []byte `protobuf:"bytes,9,opt,name=uint8_sl,json=Uint8Sl,proto3" json:"uint8_sl,omitempty"` - Uint16Sl []uint32 `protobuf:"varint,10,rep,packed,name=uint16_sl,json=Uint16Sl,proto3" json:"uint16_sl,omitempty"` - Uint32Sl []uint32 `protobuf:"varint,11,rep,packed,name=uint32_sl,json=Uint32Sl,proto3" json:"uint32_sl,omitempty"` - Uint32FixedSl []uint32 `protobuf:"fixed32,12,rep,packed,name=uint32_fixed_sl,json=Uint32FixedSl,proto3" json:"uint32_fixed_sl,omitempty"` - Uint64Sl []uint64 `protobuf:"varint,13,rep,packed,name=uint64_sl,json=Uint64Sl,proto3" json:"uint64_sl,omitempty"` - Uint64FixedSl []uint64 `protobuf:"fixed64,14,rep,packed,name=uint64_fixed_sl,json=Uint64FixedSl,proto3" json:"uint64_fixed_sl,omitempty"` - UintSl []uint64 `protobuf:"varint,15,rep,packed,name=uint_sl,json=UintSl,proto3" json:"uint_sl,omitempty"` - StrSl []string `protobuf:"bytes,16,rep,name=str_sl,json=StrSl,proto3" json:"str_sl,omitempty"` - BytesSl [][]byte `protobuf:"bytes,17,rep,name=bytes_sl,json=BytesSl,proto3" json:"bytes_sl,omitempty"` - TimeSl []*timestamppb.Timestamp `protobuf:"bytes,18,rep,name=time_sl,json=TimeSl,proto3" json:"time_sl,omitempty"` - DurationSl []*durationpb.Duration `protobuf:"bytes,19,rep,name=duration_sl,json=DurationSl,proto3" json:"duration_sl,omitempty"` - EmptySl []*EmptyStruct `protobuf:"bytes,20,rep,name=empty_sl,json=EmptySl,proto3" json:"empty_sl,omitempty"` -} - -func (x *SlicesStruct) Reset() { - *x = SlicesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SlicesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SlicesStruct) ProtoMessage() {} - -func (x *SlicesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SlicesStruct.ProtoReflect.Descriptor instead. -func (*SlicesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{5} -} - -func (x *SlicesStruct) GetInt8Sl() []int32 { - if x != nil { - return x.Int8Sl - } - return nil -} - -func (x *SlicesStruct) GetInt16Sl() []int32 { - if x != nil { - return x.Int16Sl - } - return nil -} - -func (x *SlicesStruct) GetInt32Sl() []int32 { - if x != nil { - return x.Int32Sl - } - return nil -} - -func (x *SlicesStruct) GetInt32FixedSl() []int32 { - if x != nil { - return x.Int32FixedSl - } - return nil -} - -func (x *SlicesStruct) GetInt64Sl() []int64 { - if x != nil { - return x.Int64Sl - } - return nil -} - -func (x *SlicesStruct) GetInt64FixedSl() []int64 { - if x != nil { - return x.Int64FixedSl - } - return nil -} - -func (x *SlicesStruct) GetIntSl() []int64 { - if x != nil { - return x.IntSl - } - return nil -} - -func (x *SlicesStruct) GetByteSl() []byte { - if x != nil { - return x.ByteSl - } - return nil -} - -func (x *SlicesStruct) GetUint8Sl() []byte { - if x != nil { - return x.Uint8Sl - } - return nil -} - -func (x *SlicesStruct) GetUint16Sl() []uint32 { - if x != nil { - return x.Uint16Sl - } - return nil -} - -func (x *SlicesStruct) GetUint32Sl() []uint32 { - if x != nil { - return x.Uint32Sl - } - return nil -} - -func (x *SlicesStruct) GetUint32FixedSl() []uint32 { - if x != nil { - return x.Uint32FixedSl - } - return nil -} - -func (x *SlicesStruct) GetUint64Sl() []uint64 { - if x != nil { - return x.Uint64Sl - } - return nil -} - -func (x *SlicesStruct) GetUint64FixedSl() []uint64 { - if x != nil { - return x.Uint64FixedSl - } - return nil -} - -func (x *SlicesStruct) GetUintSl() []uint64 { - if x != nil { - return x.UintSl - } - return nil -} - -func (x *SlicesStruct) GetStrSl() []string { - if x != nil { - return x.StrSl - } - return nil -} - -func (x *SlicesStruct) GetBytesSl() [][]byte { - if x != nil { - return x.BytesSl - } - return nil -} - -func (x *SlicesStruct) GetTimeSl() []*timestamppb.Timestamp { - if x != nil { - return x.TimeSl - } - return nil -} - -func (x *SlicesStruct) GetDurationSl() []*durationpb.Duration { - if x != nil { - return x.DurationSl - } - return nil -} - -func (x *SlicesStruct) GetEmptySl() []*EmptyStruct { - if x != nil { - return x.EmptySl - } - return nil -} - -type SlicesSlicesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8SlSl []*TESTS_Int8List `protobuf:"bytes,1,rep,name=int8_sl_sl,json=Int8SlSl,proto3" json:"int8_sl_sl,omitempty"` - Int16SlSl []*TESTS_Int16List `protobuf:"bytes,2,rep,name=int16_sl_sl,json=Int16SlSl,proto3" json:"int16_sl_sl,omitempty"` - Int32SlSl []*TESTS_Int32ValueList `protobuf:"bytes,3,rep,name=int32_sl_sl,json=Int32SlSl,proto3" json:"int32_sl_sl,omitempty"` - Int32FixedSlSl []*TESTS_Fixed32Int32ValueList `protobuf:"bytes,4,rep,name=int32_fixed_sl_sl,json=Int32FixedSlSl,proto3" json:"int32_fixed_sl_sl,omitempty"` - Int64SlSl []*TESTS_Int64ValueList `protobuf:"bytes,5,rep,name=int64_sl_sl,json=Int64SlSl,proto3" json:"int64_sl_sl,omitempty"` - Int64FixedSlSl []*TESTS_Fixed64Int64ValueList `protobuf:"bytes,6,rep,name=int64_fixed_sl_sl,json=Int64FixedSlSl,proto3" json:"int64_fixed_sl_sl,omitempty"` - IntSlSl []*TESTS_Int64ValueList `protobuf:"bytes,7,rep,name=int_sl_sl,json=IntSlSl,proto3" json:"int_sl_sl,omitempty"` - ByteSlSl [][]byte `protobuf:"bytes,8,rep,name=byte_sl_sl,json=ByteSlSl,proto3" json:"byte_sl_sl,omitempty"` - Uint8SlSl [][]byte `protobuf:"bytes,9,rep,name=uint8_sl_sl,json=Uint8SlSl,proto3" json:"uint8_sl_sl,omitempty"` - Uint16SlSl []*TESTS_UInt16List `protobuf:"bytes,10,rep,name=uint16_sl_sl,json=Uint16SlSl,proto3" json:"uint16_sl_sl,omitempty"` - Uint32SlSl []*TESTS_UInt32ValueList `protobuf:"bytes,11,rep,name=uint32_sl_sl,json=Uint32SlSl,proto3" json:"uint32_sl_sl,omitempty"` - Uint32FixedSlSl []*TESTS_Fixed32UInt32ValueList `protobuf:"bytes,12,rep,name=uint32_fixed_sl_sl,json=Uint32FixedSlSl,proto3" json:"uint32_fixed_sl_sl,omitempty"` - Uint64SlSl []*TESTS_UInt64ValueList `protobuf:"bytes,13,rep,name=uint64_sl_sl,json=Uint64SlSl,proto3" json:"uint64_sl_sl,omitempty"` - Uint64FixedSlSl []*TESTS_Fixed64UInt64ValueList `protobuf:"bytes,14,rep,name=uint64_fixed_sl_sl,json=Uint64FixedSlSl,proto3" json:"uint64_fixed_sl_sl,omitempty"` - UintSlSl []*TESTS_UInt64ValueList `protobuf:"bytes,15,rep,name=uint_sl_sl,json=UintSlSl,proto3" json:"uint_sl_sl,omitempty"` - StrSlSl []*TESTS_StringValueList `protobuf:"bytes,16,rep,name=str_sl_sl,json=StrSlSl,proto3" json:"str_sl_sl,omitempty"` - BytesSlSl []*TESTS_BytesList `protobuf:"bytes,17,rep,name=bytes_sl_sl,json=BytesSlSl,proto3" json:"bytes_sl_sl,omitempty"` - TimeSlSl []*TESTS_TimestampList `protobuf:"bytes,18,rep,name=time_sl_sl,json=TimeSlSl,proto3" json:"time_sl_sl,omitempty"` - DurationSlSl []*TESTS_DurationList `protobuf:"bytes,19,rep,name=duration_sl_sl,json=DurationSlSl,proto3" json:"duration_sl_sl,omitempty"` - EmptySlSl []*TESTS_EmptyStructList `protobuf:"bytes,20,rep,name=empty_sl_sl,json=EmptySlSl,proto3" json:"empty_sl_sl,omitempty"` -} - -func (x *SlicesSlicesStruct) Reset() { - *x = SlicesSlicesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SlicesSlicesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SlicesSlicesStruct) ProtoMessage() {} - -func (x *SlicesSlicesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SlicesSlicesStruct.ProtoReflect.Descriptor instead. -func (*SlicesSlicesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{6} -} - -func (x *SlicesSlicesStruct) GetInt8SlSl() []*TESTS_Int8List { - if x != nil { - return x.Int8SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt16SlSl() []*TESTS_Int16List { - if x != nil { - return x.Int16SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt32SlSl() []*TESTS_Int32ValueList { - if x != nil { - return x.Int32SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt32FixedSlSl() []*TESTS_Fixed32Int32ValueList { - if x != nil { - return x.Int32FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt64SlSl() []*TESTS_Int64ValueList { - if x != nil { - return x.Int64SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt64FixedSlSl() []*TESTS_Fixed64Int64ValueList { - if x != nil { - return x.Int64FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetIntSlSl() []*TESTS_Int64ValueList { - if x != nil { - return x.IntSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetByteSlSl() [][]byte { - if x != nil { - return x.ByteSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint8SlSl() [][]byte { - if x != nil { - return x.Uint8SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint16SlSl() []*TESTS_UInt16List { - if x != nil { - return x.Uint16SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint32SlSl() []*TESTS_UInt32ValueList { - if x != nil { - return x.Uint32SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint32FixedSlSl() []*TESTS_Fixed32UInt32ValueList { - if x != nil { - return x.Uint32FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint64SlSl() []*TESTS_UInt64ValueList { - if x != nil { - return x.Uint64SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint64FixedSlSl() []*TESTS_Fixed64UInt64ValueList { - if x != nil { - return x.Uint64FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUintSlSl() []*TESTS_UInt64ValueList { - if x != nil { - return x.UintSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetStrSlSl() []*TESTS_StringValueList { - if x != nil { - return x.StrSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetBytesSlSl() []*TESTS_BytesList { - if x != nil { - return x.BytesSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetTimeSlSl() []*TESTS_TimestampList { - if x != nil { - return x.TimeSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetDurationSlSl() []*TESTS_DurationList { - if x != nil { - return x.DurationSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetEmptySlSl() []*TESTS_EmptyStructList { - if x != nil { - return x.EmptySlSl - } - return nil -} - -type PointersStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8Pt int32 `protobuf:"zigzag32,1,opt,name=int8_pt,json=Int8Pt,proto3" json:"int8_pt,omitempty"` - Int16Pt int32 `protobuf:"zigzag32,2,opt,name=int16_pt,json=Int16Pt,proto3" json:"int16_pt,omitempty"` - Int32Pt int32 `protobuf:"zigzag32,3,opt,name=int32_pt,json=Int32Pt,proto3" json:"int32_pt,omitempty"` - Int32FixedPt int32 `protobuf:"fixed32,4,opt,name=int32_fixed_pt,json=Int32FixedPt,proto3" json:"int32_fixed_pt,omitempty"` - Int64Pt int64 `protobuf:"zigzag64,5,opt,name=int64_pt,json=Int64Pt,proto3" json:"int64_pt,omitempty"` - Int64FixedPt int64 `protobuf:"fixed64,6,opt,name=int64_fixed_pt,json=Int64FixedPt,proto3" json:"int64_fixed_pt,omitempty"` - IntPt int64 `protobuf:"zigzag64,7,opt,name=int_pt,json=IntPt,proto3" json:"int_pt,omitempty"` - BytePt uint32 `protobuf:"varint,8,opt,name=byte_pt,json=BytePt,proto3" json:"byte_pt,omitempty"` - Uint8Pt uint32 `protobuf:"varint,9,opt,name=uint8_pt,json=Uint8Pt,proto3" json:"uint8_pt,omitempty"` - Uint16Pt uint32 `protobuf:"varint,10,opt,name=uint16_pt,json=Uint16Pt,proto3" json:"uint16_pt,omitempty"` - Uint32Pt uint32 `protobuf:"varint,11,opt,name=uint32_pt,json=Uint32Pt,proto3" json:"uint32_pt,omitempty"` - Uint32FixedPt uint32 `protobuf:"fixed32,12,opt,name=uint32_fixed_pt,json=Uint32FixedPt,proto3" json:"uint32_fixed_pt,omitempty"` - Uint64Pt uint64 `protobuf:"varint,13,opt,name=uint64_pt,json=Uint64Pt,proto3" json:"uint64_pt,omitempty"` - Uint64FixedPt uint64 `protobuf:"fixed64,14,opt,name=uint64_fixed_pt,json=Uint64FixedPt,proto3" json:"uint64_fixed_pt,omitempty"` - UintPt uint64 `protobuf:"varint,15,opt,name=uint_pt,json=UintPt,proto3" json:"uint_pt,omitempty"` - StrPt string `protobuf:"bytes,16,opt,name=str_pt,json=StrPt,proto3" json:"str_pt,omitempty"` - BytesPt []byte `protobuf:"bytes,17,opt,name=bytes_pt,json=BytesPt,proto3" json:"bytes_pt,omitempty"` - TimePt *timestamppb.Timestamp `protobuf:"bytes,18,opt,name=time_pt,json=TimePt,proto3" json:"time_pt,omitempty"` - DurationPt *durationpb.Duration `protobuf:"bytes,19,opt,name=duration_pt,json=DurationPt,proto3" json:"duration_pt,omitempty"` - EmptyPt *EmptyStruct `protobuf:"bytes,20,opt,name=empty_pt,json=EmptyPt,proto3" json:"empty_pt,omitempty"` -} - -func (x *PointersStruct) Reset() { - *x = PointersStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PointersStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PointersStruct) ProtoMessage() {} - -func (x *PointersStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PointersStruct.ProtoReflect.Descriptor instead. -func (*PointersStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{7} -} - -func (x *PointersStruct) GetInt8Pt() int32 { - if x != nil { - return x.Int8Pt - } - return 0 -} - -func (x *PointersStruct) GetInt16Pt() int32 { - if x != nil { - return x.Int16Pt - } - return 0 -} - -func (x *PointersStruct) GetInt32Pt() int32 { - if x != nil { - return x.Int32Pt - } - return 0 -} - -func (x *PointersStruct) GetInt32FixedPt() int32 { - if x != nil { - return x.Int32FixedPt - } - return 0 -} - -func (x *PointersStruct) GetInt64Pt() int64 { - if x != nil { - return x.Int64Pt - } - return 0 -} - -func (x *PointersStruct) GetInt64FixedPt() int64 { - if x != nil { - return x.Int64FixedPt - } - return 0 -} - -func (x *PointersStruct) GetIntPt() int64 { - if x != nil { - return x.IntPt - } - return 0 -} - -func (x *PointersStruct) GetBytePt() uint32 { - if x != nil { - return x.BytePt - } - return 0 -} - -func (x *PointersStruct) GetUint8Pt() uint32 { - if x != nil { - return x.Uint8Pt - } - return 0 -} - -func (x *PointersStruct) GetUint16Pt() uint32 { - if x != nil { - return x.Uint16Pt - } - return 0 -} - -func (x *PointersStruct) GetUint32Pt() uint32 { - if x != nil { - return x.Uint32Pt - } - return 0 -} - -func (x *PointersStruct) GetUint32FixedPt() uint32 { - if x != nil { - return x.Uint32FixedPt - } - return 0 -} - -func (x *PointersStruct) GetUint64Pt() uint64 { - if x != nil { - return x.Uint64Pt - } - return 0 -} - -func (x *PointersStruct) GetUint64FixedPt() uint64 { - if x != nil { - return x.Uint64FixedPt - } - return 0 -} - -func (x *PointersStruct) GetUintPt() uint64 { - if x != nil { - return x.UintPt - } - return 0 -} - -func (x *PointersStruct) GetStrPt() string { - if x != nil { - return x.StrPt - } - return "" -} - -func (x *PointersStruct) GetBytesPt() []byte { - if x != nil { - return x.BytesPt - } - return nil -} - -func (x *PointersStruct) GetTimePt() *timestamppb.Timestamp { - if x != nil { - return x.TimePt - } - return nil -} - -func (x *PointersStruct) GetDurationPt() *durationpb.Duration { - if x != nil { - return x.DurationPt - } - return nil -} - -func (x *PointersStruct) GetEmptyPt() *EmptyStruct { - if x != nil { - return x.EmptyPt - } - return nil -} - -type PointerSlicesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8PtSl []int32 `protobuf:"zigzag32,1,rep,packed,name=int8_pt_sl,json=Int8PtSl,proto3" json:"int8_pt_sl,omitempty"` - Int16PtSl []int32 `protobuf:"zigzag32,2,rep,packed,name=int16_pt_sl,json=Int16PtSl,proto3" json:"int16_pt_sl,omitempty"` - Int32PtSl []int32 `protobuf:"zigzag32,3,rep,packed,name=int32_pt_sl,json=Int32PtSl,proto3" json:"int32_pt_sl,omitempty"` - Int32FixedPtSl []int32 `protobuf:"fixed32,4,rep,packed,name=int32_fixed_pt_sl,json=Int32FixedPtSl,proto3" json:"int32_fixed_pt_sl,omitempty"` - Int64PtSl []int64 `protobuf:"zigzag64,5,rep,packed,name=int64_pt_sl,json=Int64PtSl,proto3" json:"int64_pt_sl,omitempty"` - Int64FixedPtSl []int64 `protobuf:"fixed64,6,rep,packed,name=int64_fixed_pt_sl,json=Int64FixedPtSl,proto3" json:"int64_fixed_pt_sl,omitempty"` - IntPtSl []int64 `protobuf:"zigzag64,7,rep,packed,name=int_pt_sl,json=IntPtSl,proto3" json:"int_pt_sl,omitempty"` - BytePtSl []byte `protobuf:"bytes,8,opt,name=byte_pt_sl,json=BytePtSl,proto3" json:"byte_pt_sl,omitempty"` - Uint8PtSl []byte `protobuf:"bytes,9,opt,name=uint8_pt_sl,json=Uint8PtSl,proto3" json:"uint8_pt_sl,omitempty"` - Uint16PtSl []uint32 `protobuf:"varint,10,rep,packed,name=uint16_pt_sl,json=Uint16PtSl,proto3" json:"uint16_pt_sl,omitempty"` - Uint32PtSl []uint32 `protobuf:"varint,11,rep,packed,name=uint32_pt_sl,json=Uint32PtSl,proto3" json:"uint32_pt_sl,omitempty"` - Uint32FixedPtSl []uint32 `protobuf:"fixed32,12,rep,packed,name=uint32_fixed_pt_sl,json=Uint32FixedPtSl,proto3" json:"uint32_fixed_pt_sl,omitempty"` - Uint64PtSl []uint64 `protobuf:"varint,13,rep,packed,name=uint64_pt_sl,json=Uint64PtSl,proto3" json:"uint64_pt_sl,omitempty"` - Uint64FixedPtSl []uint64 `protobuf:"fixed64,14,rep,packed,name=uint64_fixed_pt_sl,json=Uint64FixedPtSl,proto3" json:"uint64_fixed_pt_sl,omitempty"` - UintPtSl []uint64 `protobuf:"varint,15,rep,packed,name=uint_pt_sl,json=UintPtSl,proto3" json:"uint_pt_sl,omitempty"` - StrPtSl []string `protobuf:"bytes,16,rep,name=str_pt_sl,json=StrPtSl,proto3" json:"str_pt_sl,omitempty"` - BytesPtSl [][]byte `protobuf:"bytes,17,rep,name=bytes_pt_sl,json=BytesPtSl,proto3" json:"bytes_pt_sl,omitempty"` - TimePtSl []*timestamppb.Timestamp `protobuf:"bytes,18,rep,name=time_pt_sl,json=TimePtSl,proto3" json:"time_pt_sl,omitempty"` - DurationPtSl []*durationpb.Duration `protobuf:"bytes,19,rep,name=duration_pt_sl,json=DurationPtSl,proto3" json:"duration_pt_sl,omitempty"` - EmptyPtSl []*EmptyStruct `protobuf:"bytes,20,rep,name=empty_pt_sl,json=EmptyPtSl,proto3" json:"empty_pt_sl,omitempty"` -} - -func (x *PointerSlicesStruct) Reset() { - *x = PointerSlicesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PointerSlicesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PointerSlicesStruct) ProtoMessage() {} - -func (x *PointerSlicesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PointerSlicesStruct.ProtoReflect.Descriptor instead. -func (*PointerSlicesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{8} -} - -func (x *PointerSlicesStruct) GetInt8PtSl() []int32 { - if x != nil { - return x.Int8PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt16PtSl() []int32 { - if x != nil { - return x.Int16PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt32PtSl() []int32 { - if x != nil { - return x.Int32PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt32FixedPtSl() []int32 { - if x != nil { - return x.Int32FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt64PtSl() []int64 { - if x != nil { - return x.Int64PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt64FixedPtSl() []int64 { - if x != nil { - return x.Int64FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetIntPtSl() []int64 { - if x != nil { - return x.IntPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetBytePtSl() []byte { - if x != nil { - return x.BytePtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint8PtSl() []byte { - if x != nil { - return x.Uint8PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint16PtSl() []uint32 { - if x != nil { - return x.Uint16PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint32PtSl() []uint32 { - if x != nil { - return x.Uint32PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint32FixedPtSl() []uint32 { - if x != nil { - return x.Uint32FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint64PtSl() []uint64 { - if x != nil { - return x.Uint64PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint64FixedPtSl() []uint64 { - if x != nil { - return x.Uint64FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUintPtSl() []uint64 { - if x != nil { - return x.UintPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetStrPtSl() []string { - if x != nil { - return x.StrPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetBytesPtSl() [][]byte { - if x != nil { - return x.BytesPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetTimePtSl() []*timestamppb.Timestamp { - if x != nil { - return x.TimePtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetDurationPtSl() []*durationpb.Duration { - if x != nil { - return x.DurationPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetEmptyPtSl() []*EmptyStruct { - if x != nil { - return x.EmptyPtSl - } - return nil -} - -type ComplexSt struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrField *PrimitivesStruct `protobuf:"bytes,1,opt,name=pr_field,json=PrField,proto3" json:"pr_field,omitempty"` - ArField *ArraysStruct `protobuf:"bytes,2,opt,name=ar_field,json=ArField,proto3" json:"ar_field,omitempty"` - SlField *SlicesStruct `protobuf:"bytes,3,opt,name=sl_field,json=SlField,proto3" json:"sl_field,omitempty"` - PtField *PointersStruct `protobuf:"bytes,4,opt,name=pt_field,json=PtField,proto3" json:"pt_field,omitempty"` -} - -func (x *ComplexSt) Reset() { - *x = ComplexSt{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComplexSt) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComplexSt) ProtoMessage() {} - -func (x *ComplexSt) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComplexSt.ProtoReflect.Descriptor instead. -func (*ComplexSt) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{9} -} - -func (x *ComplexSt) GetPrField() *PrimitivesStruct { - if x != nil { - return x.PrField - } - return nil -} - -func (x *ComplexSt) GetArField() *ArraysStruct { - if x != nil { - return x.ArField - } - return nil -} - -func (x *ComplexSt) GetSlField() *SlicesStruct { - if x != nil { - return x.SlField - } - return nil -} - -func (x *ComplexSt) GetPtField() *PointersStruct { - if x != nil { - return x.PtField - } - return nil -} - -type EmbeddedSt1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,1,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` -} - -func (x *EmbeddedSt1) Reset() { - *x = EmbeddedSt1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt1) ProtoMessage() {} - -func (x *EmbeddedSt1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt1.ProtoReflect.Descriptor instead. -func (*EmbeddedSt1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{10} -} - -func (x *EmbeddedSt1) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -type EmbeddedSt2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,1,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - ArraysStruct *ArraysStruct `protobuf:"bytes,2,opt,name=arrays_struct,json=ArraysStruct,proto3" json:"arrays_struct,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,3,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - PointersStruct *PointersStruct `protobuf:"bytes,4,opt,name=pointers_struct,json=PointersStruct,proto3" json:"pointers_struct,omitempty"` -} - -func (x *EmbeddedSt2) Reset() { - *x = EmbeddedSt2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt2) ProtoMessage() {} - -func (x *EmbeddedSt2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt2.ProtoReflect.Descriptor instead. -func (*EmbeddedSt2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{11} -} - -func (x *EmbeddedSt2) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt2) GetArraysStruct() *ArraysStruct { - if x != nil { - return x.ArraysStruct - } - return nil -} - -func (x *EmbeddedSt2) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt2) GetPointersStruct() *PointersStruct { - if x != nil { - return x.PointersStruct - } - return nil -} - -type EmbeddedSt3 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,1,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - ArraysStruct *ArraysStruct `protobuf:"bytes,2,opt,name=arrays_struct,json=ArraysStruct,proto3" json:"arrays_struct,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,3,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - PointersStruct *PointersStruct `protobuf:"bytes,4,opt,name=pointers_struct,json=PointersStruct,proto3" json:"pointers_struct,omitempty"` - EmptyStruct *EmptyStruct `protobuf:"bytes,5,opt,name=empty_struct,json=EmptyStruct,proto3" json:"empty_struct,omitempty"` -} - -func (x *EmbeddedSt3) Reset() { - *x = EmbeddedSt3{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt3) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt3) ProtoMessage() {} - -func (x *EmbeddedSt3) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt3.ProtoReflect.Descriptor instead. -func (*EmbeddedSt3) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{12} -} - -func (x *EmbeddedSt3) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt3) GetArraysStruct() *ArraysStruct { - if x != nil { - return x.ArraysStruct - } - return nil -} - -func (x *EmbeddedSt3) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt3) GetPointersStruct() *PointersStruct { - if x != nil { - return x.PointersStruct - } - return nil -} - -func (x *EmbeddedSt3) GetEmptyStruct() *EmptyStruct { - if x != nil { - return x.EmptyStruct - } - return nil -} - -type EmbeddedSt4 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Foo1 int64 `protobuf:"zigzag64,1,opt,name=foo1,json=Foo1,proto3" json:"foo1,omitempty"` - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,2,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - Foo2 string `protobuf:"bytes,3,opt,name=foo2,json=Foo2,proto3" json:"foo2,omitempty"` - ArraysStructField *ArraysStruct `protobuf:"bytes,4,opt,name=arrays_struct_field,json=ArraysStructField,proto3" json:"arrays_struct_field,omitempty"` - Foo3 []byte `protobuf:"bytes,5,opt,name=foo3,json=Foo3,proto3" json:"foo3,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,6,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - Foo4 bool `protobuf:"varint,7,opt,name=foo4,json=Foo4,proto3" json:"foo4,omitempty"` - PointersStructField *PointersStruct `protobuf:"bytes,8,opt,name=pointers_struct_field,json=PointersStructField,proto3" json:"pointers_struct_field,omitempty"` - Foo5 uint64 `protobuf:"varint,9,opt,name=foo5,json=Foo5,proto3" json:"foo5,omitempty"` -} - -func (x *EmbeddedSt4) Reset() { - *x = EmbeddedSt4{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt4) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt4) ProtoMessage() {} - -func (x *EmbeddedSt4) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt4.ProtoReflect.Descriptor instead. -func (*EmbeddedSt4) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{13} -} - -func (x *EmbeddedSt4) GetFoo1() int64 { - if x != nil { - return x.Foo1 - } - return 0 -} - -func (x *EmbeddedSt4) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt4) GetFoo2() string { - if x != nil { - return x.Foo2 - } - return "" -} - -func (x *EmbeddedSt4) GetArraysStructField() *ArraysStruct { - if x != nil { - return x.ArraysStructField - } - return nil -} - -func (x *EmbeddedSt4) GetFoo3() []byte { - if x != nil { - return x.Foo3 - } - return nil -} - -func (x *EmbeddedSt4) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt4) GetFoo4() bool { - if x != nil { - return x.Foo4 - } - return false -} - -func (x *EmbeddedSt4) GetPointersStructField() *PointersStruct { - if x != nil { - return x.PointersStructField - } - return nil -} - -func (x *EmbeddedSt4) GetFoo5() uint64 { - if x != nil { - return x.Foo5 - } - return 0 -} - -type EmbeddedSt5NameOverride struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Foo1 int64 `protobuf:"zigzag64,1,opt,name=foo1,json=Foo1,proto3" json:"foo1,omitempty"` - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,2,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - Foo2 string `protobuf:"bytes,3,opt,name=foo2,json=Foo2,proto3" json:"foo2,omitempty"` - ArraysStructField *ArraysStruct `protobuf:"bytes,4,opt,name=arrays_struct_field,json=ArraysStructField,proto3" json:"arrays_struct_field,omitempty"` - Foo3 []byte `protobuf:"bytes,5,opt,name=foo3,json=Foo3,proto3" json:"foo3,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,6,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - Foo4 bool `protobuf:"varint,7,opt,name=foo4,json=Foo4,proto3" json:"foo4,omitempty"` - PointersStructField *PointersStruct `protobuf:"bytes,8,opt,name=pointers_struct_field,json=PointersStructField,proto3" json:"pointers_struct_field,omitempty"` - Foo5 uint64 `protobuf:"varint,9,opt,name=foo5,json=Foo5,proto3" json:"foo5,omitempty"` -} - -func (x *EmbeddedSt5NameOverride) Reset() { - *x = EmbeddedSt5NameOverride{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt5NameOverride) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt5NameOverride) ProtoMessage() {} - -func (x *EmbeddedSt5NameOverride) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt5NameOverride.ProtoReflect.Descriptor instead. -func (*EmbeddedSt5NameOverride) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{14} -} - -func (x *EmbeddedSt5NameOverride) GetFoo1() int64 { - if x != nil { - return x.Foo1 - } - return 0 -} - -func (x *EmbeddedSt5NameOverride) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo2() string { - if x != nil { - return x.Foo2 - } - return "" -} - -func (x *EmbeddedSt5NameOverride) GetArraysStructField() *ArraysStruct { - if x != nil { - return x.ArraysStructField - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo3() []byte { - if x != nil { - return x.Foo3 - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo4() bool { - if x != nil { - return x.Foo4 - } - return false -} - -func (x *EmbeddedSt5NameOverride) GetPointersStructField() *PointersStruct { - if x != nil { - return x.PointersStructField - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo5() uint64 { - if x != nil { - return x.Foo5 - } - return 0 -} - -type AminoMarshalerStruct1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - C int64 `protobuf:"zigzag64,1,opt,name=c,json=C,proto3" json:"c,omitempty"` - D int64 `protobuf:"zigzag64,2,opt,name=d,json=D,proto3" json:"d,omitempty"` -} - -func (x *AminoMarshalerStruct1) Reset() { - *x = AminoMarshalerStruct1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct1) ProtoMessage() {} - -func (x *AminoMarshalerStruct1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct1.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{15} -} - -func (x *AminoMarshalerStruct1) GetC() int64 { - if x != nil { - return x.C - } - return 0 -} - -func (x *AminoMarshalerStruct1) GetD() int64 { - if x != nil { - return x.D - } - return 0 -} - -type ReprStruct1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - C int64 `protobuf:"zigzag64,1,opt,name=c,json=C,proto3" json:"c,omitempty"` - D int64 `protobuf:"zigzag64,2,opt,name=d,json=D,proto3" json:"d,omitempty"` -} - -func (x *ReprStruct1) Reset() { - *x = ReprStruct1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReprStruct1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReprStruct1) ProtoMessage() {} - -func (x *ReprStruct1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReprStruct1.ProtoReflect.Descriptor instead. -func (*ReprStruct1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{16} -} - -func (x *ReprStruct1) GetC() int64 { - if x != nil { - return x.C - } - return 0 -} - -func (x *ReprStruct1) GetD() int64 { - if x != nil { - return x.D - } - return 0 -} - -type AminoMarshalerStruct2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*ReprElem2 `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct2) Reset() { - *x = AminoMarshalerStruct2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct2) ProtoMessage() {} - -func (x *AminoMarshalerStruct2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct2.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{17} -} - -func (x *AminoMarshalerStruct2) GetValue() []*ReprElem2 { - if x != nil { - return x.Value - } - return nil -} - -type ReprElem2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,json=Key,proto3" json:"key,omitempty"` - Value *anypb.Any `protobuf:"bytes,2,opt,name=value,json=Value,proto3" json:"value,omitempty"` -} - -func (x *ReprElem2) Reset() { - *x = ReprElem2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReprElem2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReprElem2) ProtoMessage() {} - -func (x *ReprElem2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReprElem2.ProtoReflect.Descriptor instead. -func (*ReprElem2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{18} -} - -func (x *ReprElem2) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *ReprElem2) GetValue() *anypb.Any { - if x != nil { - return x.Value - } - return nil -} - -type AminoMarshalerStruct3 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value int32 `protobuf:"zigzag32,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct3) Reset() { - *x = AminoMarshalerStruct3{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct3) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct3) ProtoMessage() {} - -func (x *AminoMarshalerStruct3) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct3.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct3) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{19} -} - -func (x *AminoMarshalerStruct3) GetValue() int32 { - if x != nil { - return x.Value - } - return 0 -} - -type AminoMarshalerInt4 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - A int32 `protobuf:"zigzag32,1,opt,name=a,json=A,proto3" json:"a,omitempty"` -} - -func (x *AminoMarshalerInt4) Reset() { - *x = AminoMarshalerInt4{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerInt4) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerInt4) ProtoMessage() {} - -func (x *AminoMarshalerInt4) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerInt4.ProtoReflect.Descriptor instead. -func (*AminoMarshalerInt4) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{20} -} - -func (x *AminoMarshalerInt4) GetA() int32 { - if x != nil { - return x.A - } - return 0 -} - -type AminoMarshalerInt5 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerInt5) Reset() { - *x = AminoMarshalerInt5{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerInt5) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerInt5) ProtoMessage() {} - -func (x *AminoMarshalerInt5) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerInt5.ProtoReflect.Descriptor instead. -func (*AminoMarshalerInt5) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{21} -} - -func (x *AminoMarshalerInt5) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type AminoMarshalerStruct6 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*AminoMarshalerStruct1 `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct6) Reset() { - *x = AminoMarshalerStruct6{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct6) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct6) ProtoMessage() {} - -func (x *AminoMarshalerStruct6) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct6.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct6) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{22} -} - -func (x *AminoMarshalerStruct6) GetValue() []*AminoMarshalerStruct1 { - if x != nil { - return x.Value - } - return nil -} - -type AminoMarshalerStruct7 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct7) Reset() { - *x = AminoMarshalerStruct7{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct7) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct7) ProtoMessage() {} - -func (x *AminoMarshalerStruct7) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct7.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct7) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{23} -} - -func (x *AminoMarshalerStruct7) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type ReprElem7 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ReprElem7) Reset() { - *x = ReprElem7{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReprElem7) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReprElem7) ProtoMessage() {} - -func (x *ReprElem7) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReprElem7.ProtoReflect.Descriptor instead. -func (*ReprElem7) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{24} -} - -func (x *ReprElem7) GetValue() uint32 { - if x != nil { - return x.Value - } - return 0 -} - -type IntDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value int64 `protobuf:"zigzag64,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *IntDef) Reset() { - *x = IntDef{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntDef) ProtoMessage() {} - -func (x *IntDef) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntDef.ProtoReflect.Descriptor instead. -func (*IntDef) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{25} -} - -func (x *IntDef) GetValue() int64 { - if x != nil { - return x.Value - } - return 0 -} - -type IntAr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"zigzag64,1,rep,packed,name=value,proto3" json:"value,omitempty"` -} - -func (x *IntAr) Reset() { - *x = IntAr{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntAr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntAr) ProtoMessage() {} - -func (x *IntAr) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntAr.ProtoReflect.Descriptor instead. -func (*IntAr) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{26} -} - -func (x *IntAr) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type IntSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"zigzag64,1,rep,packed,name=value,proto3" json:"value,omitempty"` -} - -func (x *IntSl) Reset() { - *x = IntSl{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntSl) ProtoMessage() {} - -func (x *IntSl) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntSl.ProtoReflect.Descriptor instead. -func (*IntSl) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{27} -} - -func (x *IntSl) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type ByteAr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ByteAr) Reset() { - *x = ByteAr{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ByteAr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ByteAr) ProtoMessage() {} - -func (x *ByteAr) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ByteAr.ProtoReflect.Descriptor instead. -func (*ByteAr) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{28} -} - -func (x *ByteAr) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type ByteSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ByteSl) Reset() { - *x = ByteSl{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ByteSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ByteSl) ProtoMessage() {} - -func (x *ByteSl) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ByteSl.ProtoReflect.Descriptor instead. -func (*ByteSl) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{29} -} - -func (x *ByteSl) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type PrimitivesStructDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8 int32 `protobuf:"zigzag32,1,opt,name=int8,json=Int8,proto3" json:"int8,omitempty"` - Int16 int32 `protobuf:"zigzag32,2,opt,name=int16,json=Int16,proto3" json:"int16,omitempty"` - Int32 int32 `protobuf:"zigzag32,3,opt,name=int32,json=Int32,proto3" json:"int32,omitempty"` - Int32Fixed int32 `protobuf:"fixed32,4,opt,name=int32_fixed,json=Int32Fixed,proto3" json:"int32_fixed,omitempty"` - Int64 int64 `protobuf:"zigzag64,5,opt,name=int64,json=Int64,proto3" json:"int64,omitempty"` - Int64Fixed int64 `protobuf:"fixed64,6,opt,name=int64_fixed,json=Int64Fixed,proto3" json:"int64_fixed,omitempty"` - Int int64 `protobuf:"zigzag64,7,opt,name=int,json=Int,proto3" json:"int,omitempty"` - Byte uint32 `protobuf:"varint,8,opt,name=byte,json=Byte,proto3" json:"byte,omitempty"` - Uint8 uint32 `protobuf:"varint,9,opt,name=uint8,json=Uint8,proto3" json:"uint8,omitempty"` - Uint16 uint32 `protobuf:"varint,10,opt,name=uint16,json=Uint16,proto3" json:"uint16,omitempty"` - Uint32 uint32 `protobuf:"varint,11,opt,name=uint32,json=Uint32,proto3" json:"uint32,omitempty"` - Uint32Fixed uint32 `protobuf:"fixed32,12,opt,name=uint32_fixed,json=Uint32Fixed,proto3" json:"uint32_fixed,omitempty"` - Uint64 uint64 `protobuf:"varint,13,opt,name=uint64,json=Uint64,proto3" json:"uint64,omitempty"` - Uint64Fixed uint64 `protobuf:"fixed64,14,opt,name=uint64_fixed,json=Uint64Fixed,proto3" json:"uint64_fixed,omitempty"` - Uint uint64 `protobuf:"varint,15,opt,name=uint,json=Uint,proto3" json:"uint,omitempty"` - Str string `protobuf:"bytes,16,opt,name=str,json=Str,proto3" json:"str,omitempty"` - Bytes []byte `protobuf:"bytes,17,opt,name=bytes,json=Bytes,proto3" json:"bytes,omitempty"` - Time *timestamppb.Timestamp `protobuf:"bytes,18,opt,name=time,json=Time,proto3" json:"time,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,19,opt,name=duration,json=Duration,proto3" json:"duration,omitempty"` - Empty *EmptyStruct `protobuf:"bytes,20,opt,name=empty,json=Empty,proto3" json:"empty,omitempty"` -} - -func (x *PrimitivesStructDef) Reset() { - *x = PrimitivesStructDef{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructDef) ProtoMessage() {} - -func (x *PrimitivesStructDef) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructDef.ProtoReflect.Descriptor instead. -func (*PrimitivesStructDef) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{30} -} - -func (x *PrimitivesStructDef) GetInt8() int32 { - if x != nil { - return x.Int8 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt16() int32 { - if x != nil { - return x.Int16 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt32Fixed() int32 { - if x != nil { - return x.Int32Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt64Fixed() int64 { - if x != nil { - return x.Int64Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt() int64 { - if x != nil { - return x.Int - } - return 0 -} - -func (x *PrimitivesStructDef) GetByte() uint32 { - if x != nil { - return x.Byte - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint8() uint32 { - if x != nil { - return x.Uint8 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint16() uint32 { - if x != nil { - return x.Uint16 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint32() uint32 { - if x != nil { - return x.Uint32 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint32Fixed() uint32 { - if x != nil { - return x.Uint32Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint64() uint64 { - if x != nil { - return x.Uint64 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint64Fixed() uint64 { - if x != nil { - return x.Uint64Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint() uint64 { - if x != nil { - return x.Uint - } - return 0 -} - -func (x *PrimitivesStructDef) GetStr() string { - if x != nil { - return x.Str - } - return "" -} - -func (x *PrimitivesStructDef) GetBytes() []byte { - if x != nil { - return x.Bytes - } - return nil -} - -func (x *PrimitivesStructDef) GetTime() *timestamppb.Timestamp { - if x != nil { - return x.Time - } - return nil -} - -func (x *PrimitivesStructDef) GetDuration() *durationpb.Duration { - if x != nil { - return x.Duration - } - return nil -} - -func (x *PrimitivesStructDef) GetEmpty() *EmptyStruct { - if x != nil { - return x.Empty - } - return nil -} - -type PrimitivesStructSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*PrimitivesStruct `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *PrimitivesStructSl) Reset() { - *x = PrimitivesStructSl{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructSl) ProtoMessage() {} - -func (x *PrimitivesStructSl) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructSl.ProtoReflect.Descriptor instead. -func (*PrimitivesStructSl) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{31} -} - -func (x *PrimitivesStructSl) GetValue() []*PrimitivesStruct { - if x != nil { - return x.Value - } - return nil -} - -type PrimitivesStructAr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*PrimitivesStruct `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *PrimitivesStructAr) Reset() { - *x = PrimitivesStructAr{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructAr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructAr) ProtoMessage() {} - -func (x *PrimitivesStructAr) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructAr.ProtoReflect.Descriptor instead. -func (*PrimitivesStructAr) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{32} -} - -func (x *PrimitivesStructAr) GetValue() []*PrimitivesStruct { - if x != nil { - return x.Value - } - return nil -} - -type Concrete1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Concrete1) Reset() { - *x = Concrete1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Concrete1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Concrete1) ProtoMessage() {} - -func (x *Concrete1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[33] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Concrete1.ProtoReflect.Descriptor instead. -func (*Concrete1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{33} -} - -type Concrete2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Concrete2) Reset() { - *x = Concrete2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Concrete2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Concrete2) ProtoMessage() {} - -func (x *Concrete2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Concrete2.ProtoReflect.Descriptor instead. -func (*Concrete2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{34} -} - -type ConcreteTypeDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ConcreteTypeDef) Reset() { - *x = ConcreteTypeDef{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConcreteTypeDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConcreteTypeDef) ProtoMessage() {} - -func (x *ConcreteTypeDef) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[35] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConcreteTypeDef.ProtoReflect.Descriptor instead. -func (*ConcreteTypeDef) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{35} -} - -func (x *ConcreteTypeDef) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type ConcreteWrappedBytes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,json=Value,proto3" json:"value,omitempty"` -} - -func (x *ConcreteWrappedBytes) Reset() { - *x = ConcreteWrappedBytes{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConcreteWrappedBytes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConcreteWrappedBytes) ProtoMessage() {} - -func (x *ConcreteWrappedBytes) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[36] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConcreteWrappedBytes.ProtoReflect.Descriptor instead. -func (*ConcreteWrappedBytes) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{36} -} - -func (x *ConcreteWrappedBytes) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type InterfaceFieldsStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - F1 *anypb.Any `protobuf:"bytes,1,opt,name=f1,json=F1,proto3" json:"f1,omitempty"` - F2 *anypb.Any `protobuf:"bytes,2,opt,name=f2,json=F2,proto3" json:"f2,omitempty"` - F3 *anypb.Any `protobuf:"bytes,3,opt,name=f3,json=F3,proto3" json:"f3,omitempty"` - F4 *anypb.Any `protobuf:"bytes,4,opt,name=f4,json=F4,proto3" json:"f4,omitempty"` -} - -func (x *InterfaceFieldsStruct) Reset() { - *x = InterfaceFieldsStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[37] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterfaceFieldsStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterfaceFieldsStruct) ProtoMessage() {} - -func (x *InterfaceFieldsStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[37] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InterfaceFieldsStruct.ProtoReflect.Descriptor instead. -func (*InterfaceFieldsStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{37} -} - -func (x *InterfaceFieldsStruct) GetF1() *anypb.Any { - if x != nil { - return x.F1 - } - return nil -} - -func (x *InterfaceFieldsStruct) GetF2() *anypb.Any { - if x != nil { - return x.F2 - } - return nil -} - -func (x *InterfaceFieldsStruct) GetF3() *anypb.Any { - if x != nil { - return x.F3 - } - return nil -} - -func (x *InterfaceFieldsStruct) GetF4() *anypb.Any { - if x != nil { - return x.F4 - } - return nil -} - -type TESTS_BytesList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value [][]byte `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_BytesList) Reset() { - *x = TESTS_BytesList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[38] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_BytesList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_BytesList) ProtoMessage() {} - -func (x *TESTS_BytesList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[38] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_BytesList.ProtoReflect.Descriptor instead. -func (*TESTS_BytesList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{38} -} - -func (x *TESTS_BytesList) GetValue() [][]byte { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_BytesListList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*TESTS_BytesList `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_BytesListList) Reset() { - *x = TESTS_BytesListList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[39] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_BytesListList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_BytesListList) ProtoMessage() {} - -func (x *TESTS_BytesListList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[39] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_BytesListList.ProtoReflect.Descriptor instead. -func (*TESTS_BytesListList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{39} -} - -func (x *TESTS_BytesListList) GetValue() []*TESTS_BytesList { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_DurationList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*durationpb.Duration `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_DurationList) Reset() { - *x = TESTS_DurationList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[40] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_DurationList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_DurationList) ProtoMessage() {} - -func (x *TESTS_DurationList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[40] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_DurationList.ProtoReflect.Descriptor instead. -func (*TESTS_DurationList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{40} -} - -func (x *TESTS_DurationList) GetValue() []*durationpb.Duration { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_EmptyStructList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*EmptyStruct `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_EmptyStructList) Reset() { - *x = TESTS_EmptyStructList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[41] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_EmptyStructList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_EmptyStructList) ProtoMessage() {} - -func (x *TESTS_EmptyStructList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[41] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_EmptyStructList.ProtoReflect.Descriptor instead. -func (*TESTS_EmptyStructList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{41} -} - -func (x *TESTS_EmptyStructList) GetValue() []*EmptyStruct { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed32Int32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"fixed32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed32Int32ValueList) Reset() { - *x = TESTS_Fixed32Int32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[42] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed32Int32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed32Int32ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed32Int32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[42] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed32Int32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed32Int32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{42} -} - -func (x *TESTS_Fixed32Int32ValueList) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed32UInt32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint32 `protobuf:"fixed32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed32UInt32ValueList) Reset() { - *x = TESTS_Fixed32UInt32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[43] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed32UInt32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed32UInt32ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed32UInt32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[43] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed32UInt32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed32UInt32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{43} -} - -func (x *TESTS_Fixed32UInt32ValueList) GetValue() []uint32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed64Int64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"fixed64,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed64Int64ValueList) Reset() { - *x = TESTS_Fixed64Int64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[44] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed64Int64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed64Int64ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed64Int64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[44] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed64Int64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed64Int64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{44} -} - -func (x *TESTS_Fixed64Int64ValueList) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed64UInt64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint64 `protobuf:"fixed64,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed64UInt64ValueList) Reset() { - *x = TESTS_Fixed64UInt64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[45] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed64UInt64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed64UInt64ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed64UInt64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[45] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed64UInt64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed64UInt64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{45} -} - -func (x *TESTS_Fixed64UInt64ValueList) GetValue() []uint64 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int16List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"zigzag32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int16List) Reset() { - *x = TESTS_Int16List{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[46] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int16List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int16List) ProtoMessage() {} - -func (x *TESTS_Int16List) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[46] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int16List.ProtoReflect.Descriptor instead. -func (*TESTS_Int16List) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{46} -} - -func (x *TESTS_Int16List) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"zigzag32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int32ValueList) Reset() { - *x = TESTS_Int32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[47] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int32ValueList) ProtoMessage() {} - -func (x *TESTS_Int32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[47] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Int32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{47} -} - -func (x *TESTS_Int32ValueList) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"zigzag64,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int64ValueList) Reset() { - *x = TESTS_Int64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[48] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int64ValueList) ProtoMessage() {} - -func (x *TESTS_Int64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[48] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Int64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{48} -} - -func (x *TESTS_Int64ValueList) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int8List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"zigzag32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int8List) Reset() { - *x = TESTS_Int8List{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[49] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int8List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int8List) ProtoMessage() {} - -func (x *TESTS_Int8List) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[49] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int8List.ProtoReflect.Descriptor instead. -func (*TESTS_Int8List) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{49} -} - -func (x *TESTS_Int8List) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_StringValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []string `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_StringValueList) Reset() { - *x = TESTS_StringValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[50] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_StringValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_StringValueList) ProtoMessage() {} - -func (x *TESTS_StringValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[50] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_StringValueList.ProtoReflect.Descriptor instead. -func (*TESTS_StringValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{50} -} - -func (x *TESTS_StringValueList) GetValue() []string { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_TimestampList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*timestamppb.Timestamp `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_TimestampList) Reset() { - *x = TESTS_TimestampList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[51] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_TimestampList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_TimestampList) ProtoMessage() {} - -func (x *TESTS_TimestampList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[51] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_TimestampList.ProtoReflect.Descriptor instead. -func (*TESTS_TimestampList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{51} -} - -func (x *TESTS_TimestampList) GetValue() []*timestamppb.Timestamp { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_UInt16List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint32 `protobuf:"varint,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_UInt16List) Reset() { - *x = TESTS_UInt16List{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[52] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_UInt16List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_UInt16List) ProtoMessage() {} - -func (x *TESTS_UInt16List) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[52] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_UInt16List.ProtoReflect.Descriptor instead. -func (*TESTS_UInt16List) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{52} -} - -func (x *TESTS_UInt16List) GetValue() []uint32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_UInt32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint32 `protobuf:"varint,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_UInt32ValueList) Reset() { - *x = TESTS_UInt32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[53] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_UInt32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_UInt32ValueList) ProtoMessage() {} - -func (x *TESTS_UInt32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[53] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_UInt32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_UInt32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{53} -} - -func (x *TESTS_UInt32ValueList) GetValue() []uint32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_UInt64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint64 `protobuf:"varint,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_UInt64ValueList) Reset() { - *x = TESTS_UInt64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[54] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_UInt64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_UInt64ValueList) ProtoMessage() {} - -func (x *TESTS_UInt64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[54] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_UInt64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_UInt64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{54} -} - -func (x *TESTS_UInt64ValueList) GetValue() []uint64 { - if x != nil { - return x.Value - } - return nil -} - -var File_tests_proto protoreflect.FileDescriptor - -var file_tests_proto_rawDesc = []byte{ - 0x0a, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x0d, 0x0a, 0x0b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x22, - 0xc1, 0x04, 0x0a, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x11, 0x52, 0x04, 0x49, 0x6e, 0x74, 0x38, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x31, - 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x12, 0x14, - 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0a, 0x49, 0x6e, 0x74, 0x33, 0x32, - 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, - 0x52, 0x0a, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, - 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x62, 0x79, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x42, 0x79, - 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, - 0x31, 0x36, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, - 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, - 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0b, - 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, - 0x74, 0x36, 0x34, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0b, 0x55, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x69, 0x6e, 0x74, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x55, 0x69, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, - 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x53, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x84, 0x01, 0x0a, 0x11, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x61, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, 0x65, 0x41, 0x72, 0x12, 0x3a, - 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x22, 0xa1, 0x05, 0x0a, 0x0c, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, - 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x06, 0x49, 0x6e, - 0x74, 0x38, 0x41, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, 0x12, - 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0f, 0x52, 0x0c, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, - 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x12, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x10, 0x52, 0x0c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, - 0x72, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x12, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x79, 0x74, 0x65, - 0x5f, 0x61, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x42, 0x79, 0x74, 0x65, 0x41, - 0x72, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x41, 0x72, 0x12, 0x1b, 0x0a, 0x09, - 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, - 0x08, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x07, 0x52, - 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x12, 0x1b, - 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x18, 0x0d, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x0e, - 0x20, 0x03, 0x28, 0x06, 0x52, 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, - 0x64, 0x41, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x12, 0x15, 0x0a, 0x06, - 0x73, 0x74, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, - 0x72, 0x41, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x61, 0x72, 0x18, - 0x11, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x72, 0x12, 0x33, - 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, - 0x65, 0x41, 0x72, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x61, 0x72, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x12, - 0x2d, 0x0a, 0x08, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x61, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x22, 0xd6, - 0x09, 0x0a, 0x12, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, - 0x5f, 0x61, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x38, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x08, 0x49, 0x6e, 0x74, 0x38, 0x41, 0x72, 0x41, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x69, 0x6e, - 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, - 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, - 0x41, 0x72, 0x12, 0x3b, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x5f, 0x61, - 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x41, 0x72, 0x12, - 0x4d, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, - 0x72, 0x5f, 0x61, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3b, - 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, - 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x09, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x41, 0x72, 0x12, 0x4d, 0x0a, 0x11, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, 0x12, 0x37, 0x0a, 0x09, 0x69, 0x6e, - 0x74, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x41, - 0x72, 0x41, 0x72, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x5f, 0x61, - 0x72, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x41, 0x72, 0x41, - 0x72, 0x12, 0x1e, 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, - 0x18, 0x09, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x41, 0x72, 0x41, - 0x72, 0x12, 0x39, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, 0x5f, 0x61, - 0x72, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3e, 0x0a, 0x0c, - 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0b, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, - 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x41, 0x72, 0x12, 0x50, 0x0a, 0x12, - 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x5f, - 0x61, 0x72, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0f, 0x55, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3e, - 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0d, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x41, 0x72, 0x12, 0x50, - 0x0a, 0x12, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, - 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x0f, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, - 0x12, 0x3a, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x41, 0x72, 0x12, 0x38, 0x0a, 0x09, - 0x73, 0x74, 0x72, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x53, - 0x74, 0x72, 0x41, 0x72, 0x41, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, - 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x72, 0x41, 0x72, 0x12, 0x38, - 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x12, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, - 0x5f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, - 0x54, 0x69, 0x6d, 0x65, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x41, 0x72, 0x41, 0x72, 0x22, 0xa1, 0x05, 0x0a, 0x0c, 0x53, 0x6c, 0x69, 0x63, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x6e, 0x74, 0x38, - 0x5f, 0x73, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x06, 0x49, 0x6e, 0x74, 0x38, 0x53, - 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x73, 0x6c, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x73, 0x6c, 0x18, 0x03, 0x20, 0x03, 0x28, 0x11, 0x52, 0x07, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x53, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0f, 0x52, - 0x0c, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x12, 0x19, 0x0a, - 0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x12, 0x52, - 0x07, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x06, 0x20, 0x03, 0x28, 0x10, - 0x52, 0x0c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x12, 0x15, - 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x12, 0x52, 0x05, - 0x49, 0x6e, 0x74, 0x53, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x73, 0x6c, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6c, 0x12, 0x19, - 0x0a, 0x08, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x73, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x53, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, - 0x74, 0x31, 0x36, 0x5f, 0x73, 0x6c, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, - 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x73, 0x6c, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x33, - 0x32, 0x53, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x07, 0x52, 0x0d, 0x55, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, - 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x0e, 0x20, 0x03, 0x28, - 0x06, 0x52, 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, - 0x12, 0x17, 0x0a, 0x07, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x53, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x74, 0x72, - 0x5f, 0x73, 0x6c, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x72, 0x53, 0x6c, - 0x12, 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x6c, 0x18, 0x11, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x07, 0x42, 0x79, 0x74, 0x65, 0x73, 0x53, 0x6c, 0x12, 0x33, 0x0a, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x6c, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x6c, - 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x18, - 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0a, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x12, 0x2d, 0x0a, 0x08, - 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x73, 0x6c, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x6c, 0x22, 0xd6, 0x09, 0x0a, 0x12, - 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x38, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x49, - 0x6e, 0x74, 0x38, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x31, 0x36, - 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x31, 0x36, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x53, 0x6c, 0x12, - 0x3b, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x4d, 0x0a, 0x11, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, - 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3b, 0x0a, 0x0b, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x4d, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, - 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, - 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x37, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x73, - 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x53, 0x6c, 0x53, 0x6c, - 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x08, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x1e, - 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x09, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x09, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x39, - 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0a, 0x55, - 0x69, 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0a, 0x55, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x50, 0x0a, 0x12, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, - 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, - 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x55, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0f, 0x55, 0x69, 0x6e, 0x74, - 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3e, 0x0a, 0x0c, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x50, 0x0a, 0x12, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, - 0x6c, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x55, 0x49, 0x6e, - 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0f, 0x55, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3a, 0x0a, - 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x08, 0x55, 0x69, 0x6e, 0x74, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x74, 0x72, - 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x53, 0x74, 0x72, 0x53, - 0x6c, 0x53, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x6c, 0x5f, - 0x73, 0x6c, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x38, 0x0a, 0x0a, 0x74, - 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x54, 0x69, 0x6d, - 0x65, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3c, 0x0a, 0x0b, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, - 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x53, 0x6c, 0x53, 0x6c, 0x22, 0xa3, 0x05, 0x0a, 0x0e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x6e, 0x74, 0x38, 0x5f, - 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x49, 0x6e, 0x74, 0x38, 0x50, 0x74, - 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x50, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x07, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x50, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0c, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x12, 0x52, 0x07, - 0x49, 0x6e, 0x74, 0x36, 0x34, 0x50, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x36, 0x34, - 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, 0x52, - 0x0c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, 0x15, 0x0a, - 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x49, - 0x6e, 0x74, 0x50, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x70, 0x74, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x42, 0x79, 0x74, 0x65, 0x50, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x70, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x07, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x50, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, - 0x31, 0x36, 0x5f, 0x70, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, 0x6e, - 0x74, 0x31, 0x36, 0x50, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x70, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x50, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, - 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0d, 0x55, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x55, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x50, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, - 0x52, 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, - 0x17, 0x0a, 0x07, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x50, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x5f, - 0x70, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x72, 0x50, 0x74, 0x12, - 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x74, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x70, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, 0x65, 0x50, 0x74, 0x12, - 0x3a, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x74, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0a, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x74, 0x12, 0x2d, 0x0a, 0x08, 0x65, - 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x52, 0x07, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x50, 0x74, 0x22, 0x8c, 0x06, 0x0a, 0x13, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x38, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x11, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x11, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x29, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, - 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0f, 0x52, 0x0e, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x12, - 0x52, 0x09, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x29, 0x0a, 0x11, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x10, 0x52, 0x0e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1a, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, - 0x5f, 0x73, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x12, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x50, 0x74, - 0x53, 0x6c, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1e, 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x50, 0x74, - 0x53, 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x70, 0x74, 0x5f, - 0x73, 0x6c, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x50, 0x74, 0x53, 0x6c, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, - 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x07, - 0x52, 0x0f, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x53, - 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x5f, 0x73, - 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x50, - 0x74, 0x53, 0x6c, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x06, 0x52, - 0x0f, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1c, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1a, - 0x0a, 0x09, 0x73, 0x74, 0x72, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x10, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x53, 0x74, 0x72, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x38, 0x0a, 0x0a, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x54, 0x69, 0x6d, 0x65, - 0x50, 0x74, 0x53, 0x6c, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x32, 0x0a, 0x0b, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x70, - 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x50, 0x74, 0x53, 0x6c, 0x22, 0xd1, 0x01, 0x0a, 0x09, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x74, 0x12, 0x32, 0x0a, 0x08, 0x70, 0x72, 0x5f, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x50, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2e, 0x0a, 0x08, 0x61, - 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x41, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2e, 0x0a, 0x08, 0x73, - 0x6c, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x53, 0x6c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x30, 0x0a, 0x08, 0x70, - 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, 0x50, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x53, 0x0a, - 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x31, 0x12, 0x44, 0x0a, 0x11, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x22, 0x87, 0x02, 0x0a, 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, - 0x74, 0x32, 0x12, 0x44, 0x0a, 0x11, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, - 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x3e, 0x0a, 0x0f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0e, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x22, 0xbe, 0x02, 0x0a, - 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x33, 0x12, 0x44, 0x0a, 0x11, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x61, 0x72, 0x72, 0x61, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, - 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x3e, 0x0a, 0x0f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x0b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x22, 0x81, 0x03, - 0x0a, 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x34, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x31, 0x12, 0x44, 0x0a, 0x11, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x32, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x6f, 0x6f, 0x32, 0x12, 0x43, 0x0a, 0x13, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x11, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x33, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x46, 0x6f, 0x6f, 0x33, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x0c, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x34, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x46, 0x6f, - 0x6f, 0x34, 0x12, 0x49, 0x0a, 0x15, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x13, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x35, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x35, 0x22, 0x8d, 0x03, 0x0a, 0x17, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, - 0x35, 0x4e, 0x61, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x31, 0x12, 0x44, 0x0a, 0x11, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x32, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x6f, 0x6f, 0x32, 0x12, 0x43, 0x0a, 0x13, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x11, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x33, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x46, 0x6f, 0x6f, 0x33, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x0c, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x34, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x46, 0x6f, - 0x6f, 0x34, 0x12, 0x49, 0x0a, 0x15, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x13, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x35, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x35, 0x22, 0x33, 0x0a, 0x15, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, - 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x31, 0x12, 0x0c, 0x0a, 0x01, 0x63, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x01, 0x43, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x12, 0x52, 0x01, 0x44, 0x22, 0x29, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x72, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x31, 0x12, 0x0c, 0x0a, 0x01, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, - 0x52, 0x01, 0x43, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x12, 0x52, 0x01, - 0x44, 0x22, 0x3f, 0x0a, 0x15, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, - 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x32, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x52, 0x65, 0x70, 0x72, 0x45, 0x6c, 0x65, 0x6d, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x49, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x72, 0x45, 0x6c, 0x65, 0x6d, 0x32, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, - 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, - 0x15, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x33, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x12, - 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x49, 0x6e, - 0x74, 0x34, 0x12, 0x0c, 0x0a, 0x01, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x01, 0x41, - 0x22, 0x2a, 0x0a, 0x12, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, - 0x65, 0x72, 0x49, 0x6e, 0x74, 0x35, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4b, 0x0a, 0x15, - 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x36, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x41, 0x6d, 0x69, - 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x31, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x41, 0x6d, 0x69, - 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x37, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x72, - 0x45, 0x6c, 0x65, 0x6d, 0x37, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x49, - 0x6e, 0x74, 0x44, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x49, - 0x6e, 0x74, 0x41, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x12, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x49, 0x6e, - 0x74, 0x53, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x12, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x42, 0x79, 0x74, - 0x65, 0x41, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x42, 0x79, 0x74, - 0x65, 0x53, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc4, 0x04, 0x0a, 0x13, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x65, - 0x66, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, - 0x04, 0x49, 0x6e, 0x74, 0x38, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0a, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x12, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0a, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x6e, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x62, - 0x79, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x42, 0x79, 0x74, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x55, 0x69, 0x6e, 0x74, 0x38, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x12, 0x16, 0x0a, - 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0b, 0x55, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, - 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0b, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, - 0x78, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x69, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x04, 0x55, 0x69, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x53, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, - 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x43, 0x0a, 0x12, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x53, 0x6c, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x12, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x41, 0x72, 0x12, 0x2d, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x0b, 0x0a, 0x09, 0x43, 0x6f, - 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x31, 0x22, 0x0b, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x63, 0x72, - 0x65, 0x74, 0x65, 0x32, 0x22, 0x27, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x44, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, - 0x14, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xaf, 0x01, 0x0a, 0x15, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x02, 0x66, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, 0x31, 0x12, 0x24, 0x0a, 0x02, 0x66, - 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, - 0x32, 0x12, 0x24, 0x0a, 0x02, 0x66, 0x33, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, 0x33, 0x12, 0x24, 0x0a, 0x02, 0x66, 0x34, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, 0x34, 0x22, 0x27, 0x0a, - 0x0f, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a, - 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x12, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x41, 0x0a, 0x15, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x33, 0x0a, 0x1b, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, - 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0f, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x34, 0x0a, 0x1c, 0x54, 0x45, - 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x55, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x07, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x33, 0x0a, 0x1b, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, - 0x34, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x10, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x34, 0x0a, 0x1c, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, - 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x06, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x05, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x12, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x26, 0x0a, 0x0e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x38, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x11, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x54, 0x45, 0x53, 0x54, - 0x53, 0x5f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x47, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x53, - 0x5f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, - 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x28, 0x0a, 0x10, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x31, 0x36, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0d, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x54, 0x45, - 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0d, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6e, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x67, - 0x6e, 0x6f, 0x2f, 0x74, 0x6d, 0x32, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, - 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_tests_proto_rawDescOnce sync.Once - file_tests_proto_rawDescData = file_tests_proto_rawDesc -) - -func file_tests_proto_rawDescGZIP() []byte { - file_tests_proto_rawDescOnce.Do(func() { - file_tests_proto_rawDescData = protoimpl.X.CompressGZIP(file_tests_proto_rawDescData) - }) - return file_tests_proto_rawDescData -} - -var file_tests_proto_msgTypes = make([]protoimpl.MessageInfo, 55) -var file_tests_proto_goTypes = []interface{}{ - (*EmptyStruct)(nil), // 0: tests.EmptyStruct - (*PrimitivesStruct)(nil), // 1: tests.PrimitivesStruct - (*ShortArraysStruct)(nil), // 2: tests.ShortArraysStruct - (*ArraysStruct)(nil), // 3: tests.ArraysStruct - (*ArraysArraysStruct)(nil), // 4: tests.ArraysArraysStruct - (*SlicesStruct)(nil), // 5: tests.SlicesStruct - (*SlicesSlicesStruct)(nil), // 6: tests.SlicesSlicesStruct - (*PointersStruct)(nil), // 7: tests.PointersStruct - (*PointerSlicesStruct)(nil), // 8: tests.PointerSlicesStruct - (*ComplexSt)(nil), // 9: tests.ComplexSt - (*EmbeddedSt1)(nil), // 10: tests.EmbeddedSt1 - (*EmbeddedSt2)(nil), // 11: tests.EmbeddedSt2 - (*EmbeddedSt3)(nil), // 12: tests.EmbeddedSt3 - (*EmbeddedSt4)(nil), // 13: tests.EmbeddedSt4 - (*EmbeddedSt5NameOverride)(nil), // 14: tests.EmbeddedSt5NameOverride - (*AminoMarshalerStruct1)(nil), // 15: tests.AminoMarshalerStruct1 - (*ReprStruct1)(nil), // 16: tests.ReprStruct1 - (*AminoMarshalerStruct2)(nil), // 17: tests.AminoMarshalerStruct2 - (*ReprElem2)(nil), // 18: tests.ReprElem2 - (*AminoMarshalerStruct3)(nil), // 19: tests.AminoMarshalerStruct3 - (*AminoMarshalerInt4)(nil), // 20: tests.AminoMarshalerInt4 - (*AminoMarshalerInt5)(nil), // 21: tests.AminoMarshalerInt5 - (*AminoMarshalerStruct6)(nil), // 22: tests.AminoMarshalerStruct6 - (*AminoMarshalerStruct7)(nil), // 23: tests.AminoMarshalerStruct7 - (*ReprElem7)(nil), // 24: tests.ReprElem7 - (*IntDef)(nil), // 25: tests.IntDef - (*IntAr)(nil), // 26: tests.IntAr - (*IntSl)(nil), // 27: tests.IntSl - (*ByteAr)(nil), // 28: tests.ByteAr - (*ByteSl)(nil), // 29: tests.ByteSl - (*PrimitivesStructDef)(nil), // 30: tests.PrimitivesStructDef - (*PrimitivesStructSl)(nil), // 31: tests.PrimitivesStructSl - (*PrimitivesStructAr)(nil), // 32: tests.PrimitivesStructAr - (*Concrete1)(nil), // 33: tests.Concrete1 - (*Concrete2)(nil), // 34: tests.Concrete2 - (*ConcreteTypeDef)(nil), // 35: tests.ConcreteTypeDef - (*ConcreteWrappedBytes)(nil), // 36: tests.ConcreteWrappedBytes - (*InterfaceFieldsStruct)(nil), // 37: tests.InterfaceFieldsStruct - (*TESTS_BytesList)(nil), // 38: tests.TESTS_BytesList - (*TESTS_BytesListList)(nil), // 39: tests.TESTS_BytesListList - (*TESTS_DurationList)(nil), // 40: tests.TESTS_DurationList - (*TESTS_EmptyStructList)(nil), // 41: tests.TESTS_EmptyStructList - (*TESTS_Fixed32Int32ValueList)(nil), // 42: tests.TESTS_Fixed32Int32ValueList - (*TESTS_Fixed32UInt32ValueList)(nil), // 43: tests.TESTS_Fixed32UInt32ValueList - (*TESTS_Fixed64Int64ValueList)(nil), // 44: tests.TESTS_Fixed64Int64ValueList - (*TESTS_Fixed64UInt64ValueList)(nil), // 45: tests.TESTS_Fixed64UInt64ValueList - (*TESTS_Int16List)(nil), // 46: tests.TESTS_Int16List - (*TESTS_Int32ValueList)(nil), // 47: tests.TESTS_Int32ValueList - (*TESTS_Int64ValueList)(nil), // 48: tests.TESTS_Int64ValueList - (*TESTS_Int8List)(nil), // 49: tests.TESTS_Int8List - (*TESTS_StringValueList)(nil), // 50: tests.TESTS_StringValueList - (*TESTS_TimestampList)(nil), // 51: tests.TESTS_TimestampList - (*TESTS_UInt16List)(nil), // 52: tests.TESTS_UInt16List - (*TESTS_UInt32ValueList)(nil), // 53: tests.TESTS_UInt32ValueList - (*TESTS_UInt64ValueList)(nil), // 54: tests.TESTS_UInt64ValueList - (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 56: google.protobuf.Duration - (*anypb.Any)(nil), // 57: google.protobuf.Any -} -var file_tests_proto_depIdxs = []int32{ - 55, // 0: tests.PrimitivesStruct.time:type_name -> google.protobuf.Timestamp - 56, // 1: tests.PrimitivesStruct.duration:type_name -> google.protobuf.Duration - 0, // 2: tests.PrimitivesStruct.empty:type_name -> tests.EmptyStruct - 55, // 3: tests.ShortArraysStruct.time_ar:type_name -> google.protobuf.Timestamp - 56, // 4: tests.ShortArraysStruct.duration_ar:type_name -> google.protobuf.Duration - 55, // 5: tests.ArraysStruct.time_ar:type_name -> google.protobuf.Timestamp - 56, // 6: tests.ArraysStruct.duration_ar:type_name -> google.protobuf.Duration - 0, // 7: tests.ArraysStruct.empty_ar:type_name -> tests.EmptyStruct - 49, // 8: tests.ArraysArraysStruct.int8_ar_ar:type_name -> tests.TESTS_Int8List - 46, // 9: tests.ArraysArraysStruct.int16_ar_ar:type_name -> tests.TESTS_Int16List - 47, // 10: tests.ArraysArraysStruct.int32_ar_ar:type_name -> tests.TESTS_Int32ValueList - 42, // 11: tests.ArraysArraysStruct.int32_fixed_ar_ar:type_name -> tests.TESTS_Fixed32Int32ValueList - 48, // 12: tests.ArraysArraysStruct.int64_ar_ar:type_name -> tests.TESTS_Int64ValueList - 44, // 13: tests.ArraysArraysStruct.int64_fixed_ar_ar:type_name -> tests.TESTS_Fixed64Int64ValueList - 48, // 14: tests.ArraysArraysStruct.int_ar_ar:type_name -> tests.TESTS_Int64ValueList - 52, // 15: tests.ArraysArraysStruct.uint16_ar_ar:type_name -> tests.TESTS_UInt16List - 53, // 16: tests.ArraysArraysStruct.uint32_ar_ar:type_name -> tests.TESTS_UInt32ValueList - 43, // 17: tests.ArraysArraysStruct.uint32_fixed_ar_ar:type_name -> tests.TESTS_Fixed32UInt32ValueList - 54, // 18: tests.ArraysArraysStruct.uint64_ar_ar:type_name -> tests.TESTS_UInt64ValueList - 45, // 19: tests.ArraysArraysStruct.uint64_fixed_ar_ar:type_name -> tests.TESTS_Fixed64UInt64ValueList - 54, // 20: tests.ArraysArraysStruct.uint_ar_ar:type_name -> tests.TESTS_UInt64ValueList - 50, // 21: tests.ArraysArraysStruct.str_ar_ar:type_name -> tests.TESTS_StringValueList - 38, // 22: tests.ArraysArraysStruct.bytes_ar_ar:type_name -> tests.TESTS_BytesList - 51, // 23: tests.ArraysArraysStruct.time_ar_ar:type_name -> tests.TESTS_TimestampList - 40, // 24: tests.ArraysArraysStruct.duration_ar_ar:type_name -> tests.TESTS_DurationList - 41, // 25: tests.ArraysArraysStruct.empty_ar_ar:type_name -> tests.TESTS_EmptyStructList - 55, // 26: tests.SlicesStruct.time_sl:type_name -> google.protobuf.Timestamp - 56, // 27: tests.SlicesStruct.duration_sl:type_name -> google.protobuf.Duration - 0, // 28: tests.SlicesStruct.empty_sl:type_name -> tests.EmptyStruct - 49, // 29: tests.SlicesSlicesStruct.int8_sl_sl:type_name -> tests.TESTS_Int8List - 46, // 30: tests.SlicesSlicesStruct.int16_sl_sl:type_name -> tests.TESTS_Int16List - 47, // 31: tests.SlicesSlicesStruct.int32_sl_sl:type_name -> tests.TESTS_Int32ValueList - 42, // 32: tests.SlicesSlicesStruct.int32_fixed_sl_sl:type_name -> tests.TESTS_Fixed32Int32ValueList - 48, // 33: tests.SlicesSlicesStruct.int64_sl_sl:type_name -> tests.TESTS_Int64ValueList - 44, // 34: tests.SlicesSlicesStruct.int64_fixed_sl_sl:type_name -> tests.TESTS_Fixed64Int64ValueList - 48, // 35: tests.SlicesSlicesStruct.int_sl_sl:type_name -> tests.TESTS_Int64ValueList - 52, // 36: tests.SlicesSlicesStruct.uint16_sl_sl:type_name -> tests.TESTS_UInt16List - 53, // 37: tests.SlicesSlicesStruct.uint32_sl_sl:type_name -> tests.TESTS_UInt32ValueList - 43, // 38: tests.SlicesSlicesStruct.uint32_fixed_sl_sl:type_name -> tests.TESTS_Fixed32UInt32ValueList - 54, // 39: tests.SlicesSlicesStruct.uint64_sl_sl:type_name -> tests.TESTS_UInt64ValueList - 45, // 40: tests.SlicesSlicesStruct.uint64_fixed_sl_sl:type_name -> tests.TESTS_Fixed64UInt64ValueList - 54, // 41: tests.SlicesSlicesStruct.uint_sl_sl:type_name -> tests.TESTS_UInt64ValueList - 50, // 42: tests.SlicesSlicesStruct.str_sl_sl:type_name -> tests.TESTS_StringValueList - 38, // 43: tests.SlicesSlicesStruct.bytes_sl_sl:type_name -> tests.TESTS_BytesList - 51, // 44: tests.SlicesSlicesStruct.time_sl_sl:type_name -> tests.TESTS_TimestampList - 40, // 45: tests.SlicesSlicesStruct.duration_sl_sl:type_name -> tests.TESTS_DurationList - 41, // 46: tests.SlicesSlicesStruct.empty_sl_sl:type_name -> tests.TESTS_EmptyStructList - 55, // 47: tests.PointersStruct.time_pt:type_name -> google.protobuf.Timestamp - 56, // 48: tests.PointersStruct.duration_pt:type_name -> google.protobuf.Duration - 0, // 49: tests.PointersStruct.empty_pt:type_name -> tests.EmptyStruct - 55, // 50: tests.PointerSlicesStruct.time_pt_sl:type_name -> google.protobuf.Timestamp - 56, // 51: tests.PointerSlicesStruct.duration_pt_sl:type_name -> google.protobuf.Duration - 0, // 52: tests.PointerSlicesStruct.empty_pt_sl:type_name -> tests.EmptyStruct - 1, // 53: tests.ComplexSt.pr_field:type_name -> tests.PrimitivesStruct - 3, // 54: tests.ComplexSt.ar_field:type_name -> tests.ArraysStruct - 5, // 55: tests.ComplexSt.sl_field:type_name -> tests.SlicesStruct - 7, // 56: tests.ComplexSt.pt_field:type_name -> tests.PointersStruct - 1, // 57: tests.EmbeddedSt1.primitives_struct:type_name -> tests.PrimitivesStruct - 1, // 58: tests.EmbeddedSt2.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 59: tests.EmbeddedSt2.arrays_struct:type_name -> tests.ArraysStruct - 5, // 60: tests.EmbeddedSt2.slices_struct:type_name -> tests.SlicesStruct - 7, // 61: tests.EmbeddedSt2.pointers_struct:type_name -> tests.PointersStruct - 1, // 62: tests.EmbeddedSt3.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 63: tests.EmbeddedSt3.arrays_struct:type_name -> tests.ArraysStruct - 5, // 64: tests.EmbeddedSt3.slices_struct:type_name -> tests.SlicesStruct - 7, // 65: tests.EmbeddedSt3.pointers_struct:type_name -> tests.PointersStruct - 0, // 66: tests.EmbeddedSt3.empty_struct:type_name -> tests.EmptyStruct - 1, // 67: tests.EmbeddedSt4.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 68: tests.EmbeddedSt4.arrays_struct_field:type_name -> tests.ArraysStruct - 5, // 69: tests.EmbeddedSt4.slices_struct:type_name -> tests.SlicesStruct - 7, // 70: tests.EmbeddedSt4.pointers_struct_field:type_name -> tests.PointersStruct - 1, // 71: tests.EmbeddedSt5NameOverride.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 72: tests.EmbeddedSt5NameOverride.arrays_struct_field:type_name -> tests.ArraysStruct - 5, // 73: tests.EmbeddedSt5NameOverride.slices_struct:type_name -> tests.SlicesStruct - 7, // 74: tests.EmbeddedSt5NameOverride.pointers_struct_field:type_name -> tests.PointersStruct - 18, // 75: tests.AminoMarshalerStruct2.value:type_name -> tests.ReprElem2 - 57, // 76: tests.ReprElem2.value:type_name -> google.protobuf.Any - 15, // 77: tests.AminoMarshalerStruct6.value:type_name -> tests.AminoMarshalerStruct1 - 55, // 78: tests.PrimitivesStructDef.time:type_name -> google.protobuf.Timestamp - 56, // 79: tests.PrimitivesStructDef.duration:type_name -> google.protobuf.Duration - 0, // 80: tests.PrimitivesStructDef.empty:type_name -> tests.EmptyStruct - 1, // 81: tests.PrimitivesStructSl.value:type_name -> tests.PrimitivesStruct - 1, // 82: tests.PrimitivesStructAr.value:type_name -> tests.PrimitivesStruct - 57, // 83: tests.InterfaceFieldsStruct.f1:type_name -> google.protobuf.Any - 57, // 84: tests.InterfaceFieldsStruct.f2:type_name -> google.protobuf.Any - 57, // 85: tests.InterfaceFieldsStruct.f3:type_name -> google.protobuf.Any - 57, // 86: tests.InterfaceFieldsStruct.f4:type_name -> google.protobuf.Any - 38, // 87: tests.TESTS_BytesListList.Value:type_name -> tests.TESTS_BytesList - 56, // 88: tests.TESTS_DurationList.Value:type_name -> google.protobuf.Duration - 0, // 89: tests.TESTS_EmptyStructList.Value:type_name -> tests.EmptyStruct - 55, // 90: tests.TESTS_TimestampList.Value:type_name -> google.protobuf.Timestamp - 91, // [91:91] is the sub-list for method output_type - 91, // [91:91] is the sub-list for method input_type - 91, // [91:91] is the sub-list for extension type_name - 91, // [91:91] is the sub-list for extension extendee - 0, // [0:91] is the sub-list for field type_name -} - -func init() { file_tests_proto_init() } -func file_tests_proto_init() { - if File_tests_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_tests_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmptyStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShortArraysStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArraysStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArraysArraysStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SlicesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SlicesSlicesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PointersStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PointerSlicesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComplexSt); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt3); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt4); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt5NameOverride); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReprStruct1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReprElem2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct3); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerInt4); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerInt5); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct6); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct7); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReprElem7); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntAr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ByteAr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ByteSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructAr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Concrete1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Concrete2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConcreteTypeDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConcreteWrappedBytes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfaceFieldsStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_BytesList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_BytesListList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_DurationList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_EmptyStructList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed32Int32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed32UInt32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed64Int64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed64UInt64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int16List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int8List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_StringValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_TimestampList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_UInt16List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_UInt32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_UInt64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_tests_proto_rawDesc, - NumEnums: 0, - NumMessages: 55, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_tests_proto_goTypes, - DependencyIndexes: file_tests_proto_depIdxs, - MessageInfos: file_tests_proto_msgTypes, - }.Build() - File_tests_proto = out.File - file_tests_proto_rawDesc = nil - file_tests_proto_goTypes = nil - file_tests_proto_depIdxs = nil -} diff --git a/tm2/pkg/amino/tests/proto3/proto/compat.pb.go b/tm2/pkg/amino/tests/proto3/proto/compat.pb.go deleted file mode 100644 index b03a92731257..000000000000 --- a/tm2/pkg/amino/tests/proto3/proto/compat.pb.go +++ /dev/null @@ -1,1044 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.3 -// source: proto/compat.proto - -package proto3 - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type TestInt32Varint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"zigzag32,1,opt,name=Int32,proto3" json:"Int32,omitempty"` -} - -func (x *TestInt32Varint) Reset() { - *x = TestInt32Varint{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInt32Varint) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInt32Varint) ProtoMessage() {} - -func (x *TestInt32Varint) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInt32Varint.ProtoReflect.Descriptor instead. -func (*TestInt32Varint) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{0} -} - -func (x *TestInt32Varint) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -type TestInt32Fixed struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Fixed32 uint32 `protobuf:"fixed32,1,opt,name=Fixed32,proto3" json:"Fixed32,omitempty"` -} - -func (x *TestInt32Fixed) Reset() { - *x = TestInt32Fixed{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInt32Fixed) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInt32Fixed) ProtoMessage() {} - -func (x *TestInt32Fixed) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInt32Fixed.ProtoReflect.Descriptor instead. -func (*TestInt32Fixed) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{1} -} - -func (x *TestInt32Fixed) GetFixed32() uint32 { - if x != nil { - return x.Fixed32 - } - return 0 -} - -type Test32 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Foo uint32 `protobuf:"fixed32,1,opt,name=foo,proto3" json:"foo,omitempty"` - Bar int32 `protobuf:"zigzag32,2,opt,name=bar,proto3" json:"bar,omitempty"` -} - -func (x *Test32) Reset() { - *x = Test32{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Test32) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Test32) ProtoMessage() {} - -func (x *Test32) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Test32.ProtoReflect.Descriptor instead. -func (*Test32) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{2} -} - -func (x *Test32) GetFoo() uint32 { - if x != nil { - return x.Foo - } - return 0 -} - -func (x *Test32) GetBar() int32 { - if x != nil { - return x.Bar - } - return 0 -} - -type TestFixedInt64 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int64 uint64 `protobuf:"fixed64,1,opt,name=Int64,proto3" json:"Int64,omitempty"` -} - -func (x *TestFixedInt64) Reset() { - *x = TestFixedInt64{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestFixedInt64) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestFixedInt64) ProtoMessage() {} - -func (x *TestFixedInt64) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestFixedInt64.ProtoReflect.Descriptor instead. -func (*TestFixedInt64) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{3} -} - -func (x *TestFixedInt64) GetInt64() uint64 { - if x != nil { - return x.Int64 - } - return 0 -} - -type TestSFixedSInt64 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SInt64 int64 `protobuf:"fixed64,1,opt,name=SInt64,proto3" json:"SInt64,omitempty"` -} - -func (x *TestSFixedSInt64) Reset() { - *x = TestSFixedSInt64{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestSFixedSInt64) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestSFixedSInt64) ProtoMessage() {} - -func (x *TestSFixedSInt64) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestSFixedSInt64.ProtoReflect.Descriptor instead. -func (*TestSFixedSInt64) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{4} -} - -func (x *TestSFixedSInt64) GetSInt64() int64 { - if x != nil { - return x.SInt64 - } - return 0 -} - -type EmbeddedStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SomethingFixedLen int64 `protobuf:"fixed64,1,opt,name=somethingFixedLen,proto3" json:"somethingFixedLen,omitempty"` -} - -func (x *EmbeddedStruct) Reset() { - *x = EmbeddedStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedStruct) ProtoMessage() {} - -func (x *EmbeddedStruct) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedStruct.ProtoReflect.Descriptor instead. -func (*EmbeddedStruct) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{5} -} - -func (x *EmbeddedStruct) GetSomethingFixedLen() int64 { - if x != nil { - return x.SomethingFixedLen - } - return 0 -} - -type SomeStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // proto3 autom. turns this into a pointer ... - Emb *EmbeddedStruct `protobuf:"bytes,1,opt,name=emb,proto3" json:"emb,omitempty"` -} - -func (x *SomeStruct) Reset() { - *x = SomeStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SomeStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SomeStruct) ProtoMessage() {} - -func (x *SomeStruct) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SomeStruct.ProtoReflect.Descriptor instead. -func (*SomeStruct) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{6} -} - -func (x *SomeStruct) GetEmb() *EmbeddedStruct { - if x != nil { - return x.Emb - } - return nil -} - -type ProtoGotTime struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - T *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=T,proto3" json:"T,omitempty"` -} - -func (x *ProtoGotTime) Reset() { - *x = ProtoGotTime{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProtoGotTime) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProtoGotTime) ProtoMessage() {} - -func (x *ProtoGotTime) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProtoGotTime.ProtoReflect.Descriptor instead. -func (*ProtoGotTime) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{7} -} - -func (x *ProtoGotTime) GetT() *timestamppb.Timestamp { - if x != nil { - return x.T - } - return nil -} - -type TestInt32 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"varint,1,opt,name=Int32,proto3" json:"Int32,omitempty"` -} - -func (x *TestInt32) Reset() { - *x = TestInt32{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInt32) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInt32) ProtoMessage() {} - -func (x *TestInt32) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInt32.ProtoReflect.Descriptor instead. -func (*TestInt32) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{8} -} - -func (x *TestInt32) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -type TestInts struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"varint,1,opt,name=Int32,proto3" json:"Int32,omitempty"` - Int64 int64 `protobuf:"varint,2,opt,name=Int64,proto3" json:"Int64,omitempty"` -} - -func (x *TestInts) Reset() { - *x = TestInts{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInts) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInts) ProtoMessage() {} - -func (x *TestInts) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInts.ProtoReflect.Descriptor instead. -func (*TestInts) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{9} -} - -func (x *TestInts) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *TestInts) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -type IntDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val int64 `protobuf:"varint,1,opt,name=val,proto3" json:"val,omitempty"` -} - -func (x *IntDef) Reset() { - *x = IntDef{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntDef) ProtoMessage() {} - -func (x *IntDef) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntDef.ProtoReflect.Descriptor instead. -func (*IntDef) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{10} -} - -func (x *IntDef) GetVal() int64 { - if x != nil { - return x.Val - } - return 0 -} - -type IntArr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []int64 `protobuf:"varint,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *IntArr) Reset() { - *x = IntArr{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntArr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntArr) ProtoMessage() {} - -func (x *IntArr) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntArr.ProtoReflect.Descriptor instead. -func (*IntArr) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{11} -} - -func (x *IntArr) GetVal() []int64 { - if x != nil { - return x.Val - } - return nil -} - -type PrimitivesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"varint,3,opt,name=Int32,proto3" json:"Int32,omitempty"` - Int64 int64 `protobuf:"varint,4,opt,name=Int64,proto3" json:"Int64,omitempty"` - Varint int64 `protobuf:"varint,5,opt,name=Varint,proto3" json:"Varint,omitempty"` - // int int - // Byte byte = 4; // this just another varint - // Uint8 uint8 // another varint - // Uint16 uint16 // another one, also the following - // Uint32 uint32 - // Uint64 uint64 - // Uvarint uint64 `binary:"varint"` - // Uint uint - String_ string `protobuf:"bytes,14,opt,name=String,proto3" json:"String,omitempty"` - Bytes []byte `protobuf:"bytes,15,opt,name=Bytes,proto3" json:"Bytes,omitempty"` - Time *timestamppb.Timestamp `protobuf:"bytes,16,opt,name=Time,proto3" json:"Time,omitempty"` -} - -func (x *PrimitivesStruct) Reset() { - *x = PrimitivesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStruct) ProtoMessage() {} - -func (x *PrimitivesStruct) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStruct.ProtoReflect.Descriptor instead. -func (*PrimitivesStruct) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{12} -} - -func (x *PrimitivesStruct) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -func (x *PrimitivesStruct) GetVarint() int64 { - if x != nil { - return x.Varint - } - return 0 -} - -func (x *PrimitivesStruct) GetString_() string { - if x != nil { - return x.String_ - } - return "" -} - -func (x *PrimitivesStruct) GetBytes() []byte { - if x != nil { - return x.Bytes - } - return nil -} - -func (x *PrimitivesStruct) GetTime() *timestamppb.Timestamp { - if x != nil { - return x.Time - } - return nil -} - -type PrimitivesStructSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Structs []*PrimitivesStruct `protobuf:"bytes,1,rep,name=Structs,proto3" json:"Structs,omitempty"` -} - -func (x *PrimitivesStructSl) Reset() { - *x = PrimitivesStructSl{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructSl) ProtoMessage() {} - -func (x *PrimitivesStructSl) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructSl.ProtoReflect.Descriptor instead. -func (*PrimitivesStructSl) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{13} -} - -func (x *PrimitivesStructSl) GetStructs() []*PrimitivesStruct { - if x != nil { - return x.Structs - } - return nil -} - -var File_proto_compat_proto protoreflect.FileDescriptor - -var file_proto_compat_proto_rawDesc = []byte{ - 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x27, 0x0a, 0x0f, 0x54, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x22, 0x2a, 0x0a, 0x0e, 0x54, - 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x07, - 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x22, 0x2c, 0x0a, 0x06, 0x54, 0x65, 0x73, 0x74, 0x33, - 0x32, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x03, - 0x66, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, - 0x52, 0x03, 0x62, 0x61, 0x72, 0x22, 0x26, 0x0a, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x06, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x22, 0x2a, 0x0a, - 0x10, 0x54, 0x65, 0x73, 0x74, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x10, 0x52, 0x06, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x22, 0x3e, 0x0a, 0x0e, 0x45, 0x6d, 0x62, - 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x73, - 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4c, 0x65, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, 0x11, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, - 0x67, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4c, 0x65, 0x6e, 0x22, 0x3b, 0x0a, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6d, 0x62, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x52, 0x03, 0x65, 0x6d, 0x62, 0x22, 0x38, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x47, - 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x01, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x01, 0x54, - 0x22, 0x21, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, 0x0a, - 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x22, 0x36, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x73, 0x12, - 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x22, 0x1a, 0x0a, 0x06, 0x49, - 0x6e, 0x74, 0x44, 0x65, 0x66, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x1a, 0x0a, 0x06, 0x49, 0x6e, 0x74, 0x41, 0x72, - 0x72, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x03, - 0x76, 0x61, 0x6c, 0x22, 0xb4, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, - 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x12, 0x16, 0x0a, 0x06, 0x56, 0x61, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x56, 0x61, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x69, - 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x4d, 0x0a, 0x12, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x53, 0x6c, - 0x12, 0x37, 0x0a, 0x07, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x07, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_proto_compat_proto_rawDescOnce sync.Once - file_proto_compat_proto_rawDescData = file_proto_compat_proto_rawDesc -) - -func file_proto_compat_proto_rawDescGZIP() []byte { - file_proto_compat_proto_rawDescOnce.Do(func() { - file_proto_compat_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_compat_proto_rawDescData) - }) - return file_proto_compat_proto_rawDescData -} - -var file_proto_compat_proto_msgTypes = make([]protoimpl.MessageInfo, 14) -var file_proto_compat_proto_goTypes = []interface{}{ - (*TestInt32Varint)(nil), // 0: proto3tests.TestInt32Varint - (*TestInt32Fixed)(nil), // 1: proto3tests.TestInt32Fixed - (*Test32)(nil), // 2: proto3tests.Test32 - (*TestFixedInt64)(nil), // 3: proto3tests.TestFixedInt64 - (*TestSFixedSInt64)(nil), // 4: proto3tests.TestSFixedSInt64 - (*EmbeddedStruct)(nil), // 5: proto3tests.EmbeddedStruct - (*SomeStruct)(nil), // 6: proto3tests.SomeStruct - (*ProtoGotTime)(nil), // 7: proto3tests.ProtoGotTime - (*TestInt32)(nil), // 8: proto3tests.TestInt32 - (*TestInts)(nil), // 9: proto3tests.TestInts - (*IntDef)(nil), // 10: proto3tests.IntDef - (*IntArr)(nil), // 11: proto3tests.IntArr - (*PrimitivesStruct)(nil), // 12: proto3tests.PrimitivesStruct - (*PrimitivesStructSl)(nil), // 13: proto3tests.PrimitivesStructSl - (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp -} -var file_proto_compat_proto_depIdxs = []int32{ - 5, // 0: proto3tests.SomeStruct.emb:type_name -> proto3tests.EmbeddedStruct - 14, // 1: proto3tests.ProtoGotTime.T:type_name -> google.protobuf.Timestamp - 14, // 2: proto3tests.PrimitivesStruct.Time:type_name -> google.protobuf.Timestamp - 12, // 3: proto3tests.PrimitivesStructSl.Structs:type_name -> proto3tests.PrimitivesStruct - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_proto_compat_proto_init() } -func file_proto_compat_proto_init() { - if File_proto_compat_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_proto_compat_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInt32Varint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInt32Fixed); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Test32); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestFixedInt64); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestSFixedSInt64); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SomeStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoGotTime); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInt32); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInts); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntArr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_compat_proto_rawDesc, - NumEnums: 0, - NumMessages: 14, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_compat_proto_goTypes, - DependencyIndexes: file_proto_compat_proto_depIdxs, - MessageInfos: file_proto_compat_proto_msgTypes, - }.Build() - File_proto_compat_proto = out.File - file_proto_compat_proto_rawDesc = nil - file_proto_compat_proto_goTypes = nil - file_proto_compat_proto_depIdxs = nil -} diff --git a/tm2/pkg/libtm/messages/types/messages.pb.go b/tm2/pkg/libtm/messages/types/messages.pb.go deleted file mode 100644 index 5e09d2a1a112..000000000000 --- a/tm2/pkg/libtm/messages/types/messages.pb.go +++ /dev/null @@ -1,543 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v4.25.3 -// source: messages/types/proto/messages.proto - -package types - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// MessageType defines the types of messages -// that are related to the consensus process -type MessageType int32 - -const ( - MessageType_PROPOSAL MessageType = 0 - MessageType_PREVOTE MessageType = 1 - MessageType_PRECOMMIT MessageType = 2 -) - -// Enum value maps for MessageType. -var ( - MessageType_name = map[int32]string{ - 0: "PROPOSAL", - 1: "PREVOTE", - 2: "PRECOMMIT", - } - MessageType_value = map[string]int32{ - "PROPOSAL": 0, - "PREVOTE": 1, - "PRECOMMIT": 2, - } -) - -func (x MessageType) Enum() *MessageType { - p := new(MessageType) - *p = x - return p -} - -func (x MessageType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MessageType) Descriptor() protoreflect.EnumDescriptor { - return file_messages_types_proto_messages_proto_enumTypes[0].Descriptor() -} - -func (MessageType) Type() protoreflect.EnumType { - return &file_messages_types_proto_messages_proto_enumTypes[0] -} - -func (x MessageType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MessageType.Descriptor instead. -func (MessageType) EnumDescriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{0} -} - -// View is the consensus state associated with the message -type View struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // height represents the number of the proposal - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - // round represents the round number within a - // specific height (starts from 0) - Round uint64 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` -} - -func (x *View) Reset() { - *x = View{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *View) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*View) ProtoMessage() {} - -func (x *View) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use View.ProtoReflect.Descriptor instead. -func (*View) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{0} -} - -func (x *View) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *View) GetRound() uint64 { - if x != nil { - return x.Round - } - return 0 -} - -// ProposalMessage is the message containing -// the consensus proposal for the view -// -type ProposalMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // view is the current view for the message - // (the view in which the message was sent) - View *View `protobuf:"bytes,1,opt,name=view,proto3" json:"view,omitempty"` - // sender is the message sender (unique identifier) - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - // signature is the message signature of the sender - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - // proposal is the actual consensus proposal - Proposal []byte `protobuf:"bytes,4,opt,name=proposal,proto3" json:"proposal,omitempty"` - // proposalRound is the round associated with the - // proposal in the PROPOSE message. - // NOTE: this round value DOES NOT have - // to match the message view (proposal from an earlier round) - ProposalRound int64 `protobuf:"varint,5,opt,name=proposalRound,proto3" json:"proposalRound,omitempty"` -} - -func (x *ProposalMessage) Reset() { - *x = ProposalMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProposalMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProposalMessage) ProtoMessage() {} - -func (x *ProposalMessage) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProposalMessage.ProtoReflect.Descriptor instead. -func (*ProposalMessage) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{1} -} - -func (x *ProposalMessage) GetView() *View { - if x != nil { - return x.View - } - return nil -} - -func (x *ProposalMessage) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *ProposalMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *ProposalMessage) GetProposal() []byte { - if x != nil { - return x.Proposal - } - return nil -} - -func (x *ProposalMessage) GetProposalRound() int64 { - if x != nil { - return x.ProposalRound - } - return 0 -} - -// PrevoteMessage is the message -// containing the consensus proposal prevote. -// The prevote message is pretty light, -// apart from containing the view, it just -// contains a unique identifier of the proposal -// for which this prevote is meant for (ex. proposal hash) -// -type PrevoteMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // view is the current view for the message - // (the view in which the message was sent) - View *View `protobuf:"bytes,1,opt,name=view,proto3" json:"view,omitempty"` - // sender is the message sender (unique identifier) - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - // signature is the message signature of the sender - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - // identifier is the unique identifier for - // the proposal associated with this - // prevote message (ex. proposal hash) - Identifier []byte `protobuf:"bytes,4,opt,name=identifier,proto3" json:"identifier,omitempty"` -} - -func (x *PrevoteMessage) Reset() { - *x = PrevoteMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrevoteMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrevoteMessage) ProtoMessage() {} - -func (x *PrevoteMessage) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrevoteMessage.ProtoReflect.Descriptor instead. -func (*PrevoteMessage) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{2} -} - -func (x *PrevoteMessage) GetView() *View { - if x != nil { - return x.View - } - return nil -} - -func (x *PrevoteMessage) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *PrevoteMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *PrevoteMessage) GetIdentifier() []byte { - if x != nil { - return x.Identifier - } - return nil -} - -// PrecommitMessage is the message -// containing the consensus proposal precommit. -// The precommit message, same as the prevote message, -// contains a unique identifier for the proposal -// for which this precommit is meant for (ex. proposal hash) -// -type PrecommitMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // view is the current view for the message - // (the view in which the message was sent) - View *View `protobuf:"bytes,1,opt,name=view,proto3" json:"view,omitempty"` - // sender is the message sender (unique identifier) - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - // signature is the message signature of the sender - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - // identifier is the unique identifier for - // the proposal associated with this - // precommit message (ex. proposal hash) - Identifier []byte `protobuf:"bytes,4,opt,name=identifier,proto3" json:"identifier,omitempty"` -} - -func (x *PrecommitMessage) Reset() { - *x = PrecommitMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrecommitMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrecommitMessage) ProtoMessage() {} - -func (x *PrecommitMessage) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrecommitMessage.ProtoReflect.Descriptor instead. -func (*PrecommitMessage) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{3} -} - -func (x *PrecommitMessage) GetView() *View { - if x != nil { - return x.View - } - return nil -} - -func (x *PrecommitMessage) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *PrecommitMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *PrecommitMessage) GetIdentifier() []byte { - if x != nil { - return x.Identifier - } - return nil -} - -var File_messages_types_proto_messages_proto protoreflect.FileDescriptor - -var file_messages_types_proto_messages_proto_rawDesc = []byte{ - 0x0a, 0x23, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x04, 0x56, 0x69, 0x65, 0x77, 0x12, 0x16, 0x0a, - 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0xa4, 0x01, 0x0a, 0x0f, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x19, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, - 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x76, 0x6f, 0x74, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x65, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x76, - 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x56, 0x69, 0x65, 0x77, - 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2a, 0x37, 0x0a, 0x0b, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x50, - 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, - 0x56, 0x4f, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x45, 0x43, 0x4f, 0x4d, - 0x4d, 0x49, 0x54, 0x10, 0x02, 0x42, 0x11, 0x5a, 0x0f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_messages_types_proto_messages_proto_rawDescOnce sync.Once - file_messages_types_proto_messages_proto_rawDescData = file_messages_types_proto_messages_proto_rawDesc -) - -func file_messages_types_proto_messages_proto_rawDescGZIP() []byte { - file_messages_types_proto_messages_proto_rawDescOnce.Do(func() { - file_messages_types_proto_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_types_proto_messages_proto_rawDescData) - }) - return file_messages_types_proto_messages_proto_rawDescData -} - -var file_messages_types_proto_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_messages_types_proto_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_messages_types_proto_messages_proto_goTypes = []interface{}{ - (MessageType)(0), // 0: MessageType - (*View)(nil), // 1: View - (*ProposalMessage)(nil), // 2: ProposalMessage - (*PrevoteMessage)(nil), // 3: PrevoteMessage - (*PrecommitMessage)(nil), // 4: PrecommitMessage -} -var file_messages_types_proto_messages_proto_depIdxs = []int32{ - 1, // 0: ProposalMessage.view:type_name -> View - 1, // 1: PrevoteMessage.view:type_name -> View - 1, // 2: PrecommitMessage.view:type_name -> View - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_messages_types_proto_messages_proto_init() } -func file_messages_types_proto_messages_proto_init() { - if File_messages_types_proto_messages_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_messages_types_proto_messages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*View); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_messages_types_proto_messages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProposalMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_messages_types_proto_messages_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrevoteMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_messages_types_proto_messages_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrecommitMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_messages_types_proto_messages_proto_rawDesc, - NumEnums: 1, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_messages_types_proto_messages_proto_goTypes, - DependencyIndexes: file_messages_types_proto_messages_proto_depIdxs, - EnumInfos: file_messages_types_proto_messages_proto_enumTypes, - MessageInfos: file_messages_types_proto_messages_proto_msgTypes, - }.Build() - File_messages_types_proto_messages_proto = out.File - file_messages_types_proto_messages_proto_rawDesc = nil - file_messages_types_proto_messages_proto_goTypes = nil - file_messages_types_proto_messages_proto_depIdxs = nil -} diff --git a/tm2/pkg/std/package.go b/tm2/pkg/std/package.go index 76e1f9fc4add..3f71c69f0ce8 100644 --- a/tm2/pkg/std/package.go +++ b/tm2/pkg/std/package.go @@ -13,10 +13,6 @@ var Package = amino.RegisterPackage(amino.NewPackage( // Account &BaseAccount{}, "BaseAccount", - // MemFile/MemPackage - MemFile{}, "MemFile", - MemPackage{}, "MemPackage", - // Errors InternalError{}, "InternalError", TxDecodeError{}, "TxDecodeError", diff --git a/tm2/pkg/std/std.proto b/tm2/pkg/std/std.proto index 2fad1eeff38d..ead6dcf01139 100644 --- a/tm2/pkg/std/std.proto +++ b/tm2/pkg/std/std.proto @@ -15,17 +15,6 @@ message BaseAccount { uint64 sequence = 5; } -message MemFile { - string name = 1 [json_name = "Name"]; - string body = 2 [json_name = "Body"]; -} - -message MemPackage { - string name = 1 [json_name = "Name"]; - string path = 2 [json_name = "Path"]; - repeated MemFile files = 3 [json_name = "Files"]; -} - message InternalError { } diff --git a/tm2/pkg/telemetry/config/config.go b/tm2/pkg/telemetry/config/config.go index a9aa24d7848b..47fc56663420 100644 --- a/tm2/pkg/telemetry/config/config.go +++ b/tm2/pkg/telemetry/config/config.go @@ -19,9 +19,9 @@ type Config struct { func DefaultTelemetryConfig() *Config { return &Config{ MetricsEnabled: false, - MeterName: "gno.land", - ServiceName: "gno.land", - ServiceInstanceID: "gno-node-1", + MeterName: "tm2", + ServiceName: "tm2", + ServiceInstanceID: "tm2-node-1", ExporterEndpoint: "", } } From b849b5a86c46f5f417dcab4bd453e78838717f4b Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:18:00 -0500 Subject: [PATCH 28/31] ci: run gno test with --print-runtime-metrics (#2979) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enabling `--print-runtime-metrics` on the CI triggered a bug. One of our libraries passes without the flag but triggers a panic with the message `allocation limit exceeded` when the flag is present. I suspect this check occurs with the `gno` CLI when the flag is enabled and also on-chain. Therefore, it may be a minor bug affecting local development, particularly for unit tests. Regardless, it deserves investigation. --- Diff too long (47Mb); embedding only the first and last 100 lines. ```console $> go run github.com/gnolang/gno/gnovm/cmd/gno test -v -update-golden-tests -print-runtime-metrics ./examples/gno.land/p/demo/diff === RUN TestMyersDiff === RUN TestMyersDiff/No_difference --- PASS: TestMyersDiff/No_difference (0.00s) === RUN TestMyersDiff/Simple_insertion --- PASS: TestMyersDiff/Simple_insertion (0.00s) === RUN TestMyersDiff/Simple_deletion --- PASS: TestMyersDiff/Simple_deletion (0.00s) === RUN TestMyersDiff/Simple_substitution --- PASS: TestMyersDiff/Simple_substitution (0.00s) === RUN TestMyersDiff/Multiple_changes --- PASS: TestMyersDiff/Multiple_changes (0.00s) === RUN TestMyersDiff/Prefix_and_suffix --- PASS: TestMyersDiff/Prefix_and_suffix (0.00s) === RUN TestMyersDiff/Complete_change --- PASS: TestMyersDiff/Complete_change (0.00s) === RUN TestMyersDiff/Empty_strings --- PASS: TestMyersDiff/Empty_strings (0.00s) === RUN TestMyersDiff/Old_empty --- PASS: TestMyersDiff/Old_empty (0.00s) === RUN TestMyersDiff/New_empty --- PASS: TestMyersDiff/New_empty (0.00s) === RUN TestMyersDiff/non-ascii_(Korean_characters) --- PASS: TestMyersDiff/non-ascii_(Korean_characters) (0.00s) === RUN TestMyersDiff/Emoji_diff --- PASS: TestMyersDiff/Emoji_diff (0.00s) === RUN TestMyersDiff/Mixed_multibyte_and_ASCII --- PASS: TestMyersDiff/Mixed_multibyte_and_ASCII (0.00s) === RUN TestMyersDiff/Chinese_characters --- PASS: TestMyersDiff/Chinese_characters (0.00s) === RUN TestMyersDiff/Combining_characters --- PASS: TestMyersDiff/Combining_characters (0.00s) === RUN TestMyersDiff/Right-to-Left_languages --- PASS: TestMyersDiff/Right-to-Left_languages (0.00s) === RUN TestMyersDiff/Normalization_NFC_and_NFD --- PASS: TestMyersDiff/Normalization_NFC_and_NFD (0.00s) === RUN TestMyersDiff/Case_sensitivity --- PASS: TestMyersDiff/Case_sensitivity (0.00s) === RUN TestMyersDiff/Surrogate_pairs --- PASS: TestMyersDiff/Surrogate_pairs (0.00s) === RUN TestMyersDiff/Control_characters --- PASS: TestMyersDiff/Control_characters (0.00s) === RUN TestMyersDiff/Mixed_scripts --- PASS: TestMyersDiff/Mixed_scripts (0.00s) === RUN TestMyersDiff/Unicode_normalization --- PASS: TestMyersDiff/Unicode_normalization (0.00s) === RUN TestMyersDiff/Directional_marks --- PASS: TestMyersDiff/Directional_marks (0.00s) === RUN TestMyersDiff/Zero-width_characters --- PASS: TestMyersDiff/Zero-width_characters (0.00s) === RUN TestMyersDiff/Worst-case_scenario_(completely_different_strings) ./examples/gno.land/p/demo/diff: test pkg: panic: allocation limit exceeded stack: goroutine 1 [running]: runtime/debug.Stack() /nix/store/05saqcgidraqmn4z82prsp7rbj9hjmwm-go-1.22.5/share/go/src/runtime/debug/stack.go:24 +0x64 main.runTestFiles.func1() /Users/moul/go/src/github.com/gnolang/gno/gnovm/cmd/gno/test.go:427 +0x48 panic({0x102ba10c0?, 0x102d07500?}) /nix/store/05saqcgidraqmn4z82prsp7rbj9hjmwm-go-1.22.5/share/go/src/runtime/panic.go:770 +0x124 github.com/gnolang/gno/gnovm/pkg/gnolang.(*Allocator).Allocate(...) /Users/moul/go/src/github.com/gnolang/gno/gnovm/pkg/gnolang/alloc.go:107 github.com/gnolang/gno/gnovm/pkg/gnolang.(*Allocator).AllocateBlock(...) /Users/moul/go/src/github.com/gnolang/gno/gnovm/pkg/gnolang/alloc.go:157 github.com/gnolang/gno/gnovm/pkg/gnolang.(*Allocator).NewBlock(0x14000010af0, {0x102d27610, 0x14000101b08}, 0x14014a352c0) /Users/moul/go/src/github.com/gnolang/gno/gnovm/pkg/gnolang/alloc.go:291 +0x90 github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).doOpExec(0x140003d0908, 0x1?) /Users/moul/go/src/github.com/gnolang/gno/gnovm/pkg/gnolang/op_exec.go:519 +0x2880 github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).Run(0x140003d0908) /Users/moul/go/src/github.com/gnolang/gno/gnovm/pkg/gnolang/machine.go:1593 +0xaec github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).Eval(0x140003d0908, {0x102d1da40, 0x1400b1ae2a0}) /Users/moul/go/src/github.com/gnolang/gno/gnovm/pkg/gnolang/machine.go:884 +0x584 main.runTestFiles(0x140003d0908, 0x140001a5710, {0x140004acbd8, 0x4}, 0x1, 0x1, {0x0, 0x0}, {0x102d20870, 0x140004ab220}) /Users/moul/go/src/github.com/gnolang/gno/gnovm/cmd/gno/test.go:453 +0x2ac main.gnoTestPkg({0x16ddc2824, 0x1f}, {0x1400043cfd0?, 0x1, 0x0?}, {0x0, 0x0, 0x930abcef00000000?}, 0x14000417a80, {0x102d20870, ...}) /Users/moul/go/src/github.com/gnolang/gno/gnovm/cmd/gno/test.go:298 +0xe94 main.execTest(0x14000417a80, {0x1400043cf80?, 0x1?, 0x1?}, {0x102d20870, 0x140004ab220}) /Users/moul/go/src/github.com/gnolang/gno/gnovm/cmd/gno/test.go:197 +0x35c main.newTestCmd.func1({0x0?, 0x140001ae170?}, {0x1400043cf80?, 0x1400040e6c0?, 0x0?}) /Users/moul/go/src/github.com/gnolang/gno/gnovm/cmd/gno/test.go:98 +0x3c github.com/gnolang/gno/tm2/pkg/commands.(*Command).Run(0x14000438f20?, {0x102d136f0?, 0x1033f5e40?}) /Users/moul/go/src/github.com/gnolang/gno/tm2/pkg/commands/command.go:255 +0x17c github.com/gnolang/gno/tm2/pkg/commands.(*Command).Run(0x14000438f20?, {0x102d136f0?, 0x1033f5e40?}) /Users/moul/go/src/github.com/gnolang/gno/tm2/pkg/commands/command.go:259 +0x12c github.com/gnolang/gno/tm2/pkg/commands.(*Command).ParseAndRun(0x14000438f20, {0x102d136f0, 0x1033f5e40}, {0x140001ae130?, 0x140004394a0?, 0x14000439550?}) /Users/moul/go/src/github.com/gnolang/gno/tm2/pkg/commands/command.go:140 +0x4c github.com/gnolang/gno/tm2/pkg/commands.(*Command).Execute(0x102d20870?, {0x102d136f0?, 0x1033f5e40?}, {0x140001ae130?, 0x103311f28?, 0x140000021c0?}) /Users/moul/go/src/github.com/gnolang/gno/tm2/pkg/commands/command.go:117 +0x28 main.main() /Users/moul/go/src/github.com/gnolang/gno/gnovm/cmd/gno/main.go:13 +0x6c gno machine: Machine: CheckTypes: false Op: [OpHalt OpBody OpRangeIter OpPopBlock OpBody OpReturn OpBody OpPopResults OpExec OpBody OpPopResults OpExec OpBody OpRangeIter OpPopResults OpBody OpPopResults OpExec OpBody OpPopResults OpExec OpBody OpDefine OpBody OpForLoop OpForLoop] Values: (len: 10) #9 (MyersDiff func(old string,new string)( []gno.land/p/demo/diff.Edit)) #8 (func(t *testing.T)(){...} testing.testingFunc) #7 (tRunner func(t *testing.T,fn testing.testingFunc,verbose bool)()) #6 (<*testing.T>.Run(t *testing.T,name string,f testing.testingFunc)( bool) func(name string,f testing.testingFunc)( bool)) #5 (slice[(struct{("No difference" string),("abc" string),("abc" string),("abc" string)} struct{name string;old string;new string;expected string}),(struct{("Simple insertion" string),("ac" string),("abc" string),("a[+b]c" string)} struct{name string;old string;new string;expected string}),(struct{("Simple deletion" string),("abc" string),("ac" string),("a[-b]c" string)} struct{name string;old string;new string;expected string}),(struct{("Simple substitution" string),("abc" string),("abd" string),("ab[-c][+d]" string)} struct{name string;old string;new string;expected string}),(struct{("Multiple changes" string),("The quick brown fox jumps over the lazy dog" string),("The quick brown cat jumps over the lazy dog" string),("The quick brown [-fox][+cat] jumps over the lazy dog" string)} struct{name string;old string;new string;expected string}),(struct{("Prefix and suffix" string),("Hello, world!" string),("Hello, beautiful world!" string),("Hello, [+beautiful ]world!" string)} struct{name string;old string;new string;expected string}),(struct{("Complete change" string),("abcdef" string),("ghijkl" string),("[-abcdef][+ghijkl]" string)} struct{name string;old string;new string;expected string}),(struct{("Empty strings" string),("" string),("" string),("" string)} struct{name string;old string;new string;expected string}),(struct{("Old empty" string),("" string),("abc" string),("[+abc]" string)} struct{name string;old string;new string;expected string}),(struct{("New empty" string),("abc" string),("" string),("[-abc]" string)} struct{name string;old string;new string;expected string}),(struct{("non-ascii (Korean characters)" string),("ASCII 문자가 아닌 것도 되나?" string),("ASCII 문자가 아닌 것도 됨." string),("ASCII 문자가 아닌 것도 [-되나?][+됨.]" string)} struct{name string;old string;new string;expected string}),(struct{("Emoji diff" string),("Hello 👋 World 🌍" string),("Hello 👋 Beautiful 🌸 World 🌍" string),("Hello 👋 [+Beautiful 🌸 ]World 🌍" string)} struct{name string;old string;new string;expected string}),(struct{("Mixed multibyte and ASCII" string),("こんにちは World" string),("こんばんは World" string),("こん[-にち][+ばん]は World" string)} struct{name string;old string;new string;expected string}),(struct{("Chinese characters" string),("我喜欢编程" string),("我喜欢看书和编程" string),("我喜欢[+看书和]编程" string)} struct{name string;old string;new string;expected string}),(struct{("Combining characters" string),("é" string),("è" string),("e[-́][+̀]" string)} struct{name string;old string;new string;expected string}),(struct{("Right-to-Left languages" string),("שלום" string),("שלום עולם" string),("שלום[+ עולם]" string)} struct{name string;old string;new string;expected string}),(struct{("Normalization NFC and NFD" string),("é" string),("é" string),("[-é][+é]" string)} struct{name string;old string;new string;expected string}),(struct{("Case sensitivity" string),("abc" string),("Abc" string),("[-a][+A]bc" string)} struct{name string;old string;new string;expected string}),(struct{("Surrogate pairs" string),("Hello 🌍" string),("Hello 🌎" string),("Hello [-🌍][+🌎]" string)} struct{name string;old string;new string;expected string}),(struct{("Control characters" string),("Line1\nLine2" string),("Line1\r\nLine2" string),("Line1[+\r]\nLine2" string)} struct{name string;old string;new string;expected string}),(struct{("Mixed scripts" string),("Hello नमस्ते こんにちは" string),("Hello สวัสดี こんにちは" string),("Hello [-नमस्ते][+สวัสดี] こんにちは" string)} struct{name string;old string;new string;expected string}),(struct{("Unicode normalization" string),("é" string),("é" string),("[-é][+é]" string)} struct{name string;old string;new string;expected string}),(struct{("Directional marks" string),("Hello\u200eworld" string),("Hello\u200fworld" string),("Hello[-\u200e][+\u200f]world" string)} struct{name string;old string;new string;expected string}),(struct{("Zero-width characters" string),("ab\u200bc" string),("abc" string),("ab[-\u200b]c" string)} struct{name string;old string;new string;expected string}),(struct{("Worst-case scenario (completely different strings)" string),("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" string),("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" string),("[-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa][+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb]" string)} struct{name string;old string;new string;expected string}),(struct{("Very long strings" string),("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" string),("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" string),("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[-b][+c]aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" string)} struct{name string;old string;new string;expected string})] []struct{name string;old string;new string;expected string}) #4 (TestMyersDiff testing.testingFunc) [...] t: (&(struct{("TestMyersDiff/Worst-case_scenario_(completely_different_strings)" string),(false bool),(false bool),(nil []*testing.T),(&(struct{("TestMyersDiff" string),(false bool),(false bool),(slice[(&(struct{("TestMyersDiff/No_difference" string),(false bool),(false bool),(nil []*testing.T),(0x1400b0a7830 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_insertion" string),(false bool),(false bool),(nil []*testing.T),(0x1400b0a7bf0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_deletion" string),(false bool),(false bool),(nil []*testing.T),(0x14017b42000 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_substitution" string),(false bool),(false bool),(nil []*testing.T),(0x14017b422a0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Multiple_changes" string),(false bool),(false bool),(nil []*testing.T),(0x14017b42510 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Prefix_and_suffix" string),(false bool),(false bool),(nil []*testing.T),(0x14017b42780 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Complete_change" string),(false bool),(false bool),(nil []*testing.T),(0x14017b429f0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Empty_strings" string),(false bool),(false bool),(nil []*testing.T),(0x14017b42c60 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Old_empty" string),(false bool),(false bool),(nil []*testing.T),(0x14017b42ed0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/New_empty" string),(false bool),(false bool),(nil []*testing.T),(0x14017b43140 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/non-ascii_(Korean_characters)" string),(false bool),(false bool),(nil []*testing.T),(0x14017b433b0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Emoji_diff" string),(false bool),(false bool),(nil []*testing.T),(0x14017b43620 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Mixed_multibyte_and_ASCII" string),(false bool),(false bool),(nil []*testing.T),(0x14017b43890 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Chinese_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14017b43b00 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Combining_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14017b43d70 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Right-to-Left_languages" string),(false bool),(false bool),(nil []*testing.T),(0x14017a62060 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Normalization_NFC_and_NFD" string),(false bool),(false bool),(nil []*testing.T),(0x14017a622d0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Case_sensitivity" string),(false bool),(false bool),(nil []*testing.T),(0x14017a62570 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Surrogate_pairs" string),(false bool),(false bool),(nil []*testing.T),(0x14017a627e0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Control_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14017a62a50 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Mixed_scripts" string),(false bool),(false bool),(nil []*testing.T),(0x14017a62cc0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Unicode_normalization" string),(false bool),(false bool),(nil []*testing.T),(0x14017a62f30 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Directional_marks" string),(false bool),(false bool),(nil []*testing.T),(0x14017a631a0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Zero-width_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14017a63410 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(0x14017a63500 *testing.T)] []*testing.T),(nil *testing.T),(nil []uint8),(true bool),(undefined),( string)} testing.T) *testing.T),(nil []uint8),(true bool),(undefined),( string)} testing.T) *testing.T) diff: (undefined) result: (undefined) (static) #10 Block(ID:0000000000000000000000000000000000000000:0,Addr:0x140004dee30,Source:func func(t *(testing)) Run...,Parent:0x1400668ad20) t: (&(struct{("TestMyersDiff" string),(false bool),(false bool),(slice[(&(struct{("TestMyersDiff/No_difference" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d8180 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_insertion" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d8540 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_deletion" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d8930 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_substitution" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d8ba0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Multiple_changes" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d8ed0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Prefix_and_suffix" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d9290 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Complete_change" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d95c0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Empty_strings" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d98f0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Old_empty" string),(false bool),(false bool),(nil []*testing.T),(0x1400d1d9c50 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/New_empty" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb8000 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/non-ascii_(Korean_characters)" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb8270 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Emoji_diff" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb8510 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Mixed_multibyte_and_ASCII" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb8780 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Chinese_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb89f0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Combining_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb8c60 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Right-to-Left_languages" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb8ed0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Normalization_NFC_and_NFD" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb9140 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Case_sensitivity" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb93b0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Surrogate_pairs" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb9620 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Control_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb9890 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Mixed_scripts" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb9b00 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Unicode_normalization" string),(false bool),(false bool),(nil []*testing.T),(0x14014fb9d70 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Directional_marks" string),(false bool),(false bool),(nil []*testing.T),(0x14008bda060 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Zero-width_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14008bda2d0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Worst-case_scenario_(completely_different_strings)" string),(false bool),(false bool),(nil []*testing.T),(0x14008bda540 *testing.T),(nil []uint8),(true bool),(undefined),( string)} testing.T) *testing.T)] []*testing.T),(nil *testing.T),(nil []uint8),(true bool),(undefined),( string)} testing.T) *testing.T) name: ("Worst-case scenario (completely different strings)" string) f: (func(t *testing.T)(){...} testing.testingFunc) fullName: ("TestMyersDiff/Worst-case_scenario_(completely_different_strings)" string) subT: (&(struct{("TestMyersDiff/Worst-case_scenario_(completely_different_strings)" string),(false bool),(false bool),(nil []*testing.T),(&(struct{("TestMyersDiff" string),(false bool),(false bool),(slice[(&(struct{("TestMyersDiff/No_difference" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdac90 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_insertion" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdaf00 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_deletion" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdb170 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Simple_substitution" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdb3e0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Multiple_changes" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdb650 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Prefix_and_suffix" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdb8f0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Complete_change" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdbb60 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Empty_strings" string),(false bool),(false bool),(nil []*testing.T),(0x14008bdbe00 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Old_empty" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6c0f0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/New_empty" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6c360 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/non-ascii_(Korean_characters)" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6c600 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Emoji_diff" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6c870 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Mixed_multibyte_and_ASCII" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6cae0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Chinese_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6cd50 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Combining_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6cfc0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Right-to-Left_languages" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6d230 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Normalization_NFC_and_NFD" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6d4d0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Case_sensitivity" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6d740 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Surrogate_pairs" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6d9b0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Control_characters" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6dc20 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Mixed_scripts" string),(false bool),(false bool),(nil []*testing.T),(0x14008c6de90 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Unicode_normalization" string),(false bool),(false bool),(nil []*testing.T),(0x14008944180 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Directional_marks" string),(false bool),(false bool),(nil []*testing.T),(0x14008944420 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(&(struct{("TestMyersDiff/Zero-width_characters" string),(false bool),(false bool),(nil []*testing.T),(0x140089446c0 *testing.T),(nil []uint8),(true bool),(undefined),("0.00s" string)} testing.T) *testing.T),(0x140089447b0 *testing.T)] []*testing.T),(nil *testing.T),(nil []uint8),(true bool),(undefined),( string)} testing.T) *testing.T),(nil []uint8),(true bool),(undefined),( string)} testing.T) *testing.T) .res_0: (undefined) (static) #8 Block(ID:0000000000000000000000000000000000000000:0,Addr:0x14006babc30,Source:func (t *(T)) Run...,Parent:0x14006bd2330) t: (nil *testing.T) name: ( string) f: (nil testing.testingFunc) fullName: ( string) subT: (nil *testing.T) .res_0: (false bool) #7 Block(ID:0000000000000000000000000000000000000000:0,Addr:0x14006ac65a0,Source:for _, tc, tc.Name == na...,Parent:0x14006766b40) (static) #3 Block(ID:0000000000000000000000000000000000000000:0,Addr:0x140088c8d30,Source:if test.Name == na...,Parent:0x14007895530) #2 Block(ID:0000000000000000000000000000000000000000:0,Addr:0x14006766b40,Source:for _, test, test --- .github/workflows/examples.yml | 2 +- gnovm/cmd/gno/test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 77d40098900c..7c4bb35526ff 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,7 +47,7 @@ jobs: echo "LOG_LEVEL=debug" >> $GITHUB_ENV echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - run: go install -v ./gnovm/cmd/gno - - run: go run ./gnovm/cmd/gno test -v -print-events ./examples/... + - run: go run ./gnovm/cmd/gno test -v -print-runtime-metrics -print-events ./examples/... lint: strategy: fail-fast: false diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index c6feebfd2b5e..d54b12f6a4fa 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -7,6 +7,7 @@ import ( "flag" "fmt" "log" + "math" "os" "path/filepath" "runtime/debug" @@ -300,7 +301,7 @@ func gnoTestPkg( if printRuntimeMetrics { // from tm2/pkg/sdk/vm/keeper.go // XXX: make maxAllocTx configurable. - maxAllocTx := int64(500 * 1000 * 1000) + maxAllocTx := int64(math.MaxInt64) m.Alloc = gno.NewAllocator(maxAllocTx) } From 49e718c0fb98fe221b8c990b4c539cee221dc4e3 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:32:06 -0500 Subject: [PATCH 29/31] feat: add `p/moul/txlink` + `p/moul/helplink` (#2887) This PR aimed to promote the use of a `p/` library for managing special help links from contracts. It also provided an opportunity for me to realize that our discussion about changing the `$` symbol would require some parsing and detection from the `gnoweb` perspective. If we want a simple library like this one, the goal should be to ideally craft a link to the current package without specifying the realm path. Relative URLs worked well with `?`, but they won't function with `$`. As an alternative, we can have this package look for `std.PrevRealm().PkgAddr` if it is not specified. cc @jeronimoalbi @thehowl @leohhhn Related with #2602 Related with #2876 --------- Signed-off-by: moul <94029+moul@users.noreply.github.com> Co-authored-by: Leon Hudak <33522493+leohhhn@users.noreply.github.com> --- examples/gno.land/p/moul/helplink/gno.mod | 6 ++ .../gno.land/p/moul/helplink/helplink.gno | 79 +++++++++++++++++++ .../p/moul/helplink/helplink_test.gno | 78 ++++++++++++++++++ examples/gno.land/p/moul/txlink/gno.mod | 3 + examples/gno.land/p/moul/txlink/txlink.gno | 74 +++++++++++++++++ .../gno.land/p/moul/txlink/txlink_test.gno | 37 +++++++++ examples/gno.land/r/demo/boards/board.gno | 5 +- examples/gno.land/r/demo/boards/gno.mod | 1 + examples/gno.land/r/demo/boards/post.gno | 30 +++---- .../gno.land/r/demo/boards/z_0_filetest.gno | 2 +- .../r/demo/boards/z_10_c_filetest.gno | 6 +- .../gno.land/r/demo/boards/z_10_filetest.gno | 2 +- .../r/demo/boards/z_11_d_filetest.gno | 8 +- .../gno.land/r/demo/boards/z_11_filetest.gno | 4 +- .../gno.land/r/demo/boards/z_12_filetest.gno | 2 +- .../gno.land/r/demo/boards/z_2_filetest.gno | 4 +- .../gno.land/r/demo/boards/z_3_filetest.gno | 4 +- .../gno.land/r/demo/boards/z_4_filetest.gno | 6 +- .../gno.land/r/demo/boards/z_5_c_filetest.gno | 4 +- .../gno.land/r/demo/boards/z_5_filetest.gno | 6 +- .../gno.land/r/demo/boards/z_6_filetest.gno | 8 +- .../gno.land/r/demo/boards/z_7_filetest.gno | 2 +- .../gno.land/r/demo/boards/z_8_filetest.gno | 4 +- .../gno.land/r/demo/boards/z_9_filetest.gno | 2 +- 24 files changed, 327 insertions(+), 50 deletions(-) create mode 100644 examples/gno.land/p/moul/helplink/gno.mod create mode 100644 examples/gno.land/p/moul/helplink/helplink.gno create mode 100644 examples/gno.land/p/moul/helplink/helplink_test.gno create mode 100644 examples/gno.land/p/moul/txlink/gno.mod create mode 100644 examples/gno.land/p/moul/txlink/txlink.gno create mode 100644 examples/gno.land/p/moul/txlink/txlink_test.gno diff --git a/examples/gno.land/p/moul/helplink/gno.mod b/examples/gno.land/p/moul/helplink/gno.mod new file mode 100644 index 000000000000..1b1067492606 --- /dev/null +++ b/examples/gno.land/p/moul/helplink/gno.mod @@ -0,0 +1,6 @@ +module gno.land/p/moul/helplink + +require ( + gno.land/p/demo/urequire v0.0.0-latest + gno.land/p/moul/txlink v0.0.0-latest +) diff --git a/examples/gno.land/p/moul/helplink/helplink.gno b/examples/gno.land/p/moul/helplink/helplink.gno new file mode 100644 index 000000000000..b9ac8e102b9d --- /dev/null +++ b/examples/gno.land/p/moul/helplink/helplink.gno @@ -0,0 +1,79 @@ +// Package helplink provides utilities for creating help page links compatible +// with Gnoweb, Gnobro, and other clients that support the Gno contracts' +// flavored Markdown format. +// +// This package simplifies the generation of dynamic, context-sensitive help +// links, enabling users to navigate relevant documentation seamlessly within +// the Gno ecosystem. +// +// For a more lightweight alternative, consider using p/moul/txlink. +// +// The primary functions — Func, FuncURL, and Home — are intended for use with +// the "relative realm". When specifying a custom Realm, you can create links +// that utilize either the current realm path or a fully qualified path to +// another realm. +package helplink + +import ( + "strings" + + "gno.land/p/moul/txlink" +) + +const chainDomain = "gno.land" // XXX: std.ChainDomain (#2911) + +// Func returns a markdown link for the specific function with optional +// key-value arguments, for the current realm. +func Func(title string, fn string, args ...string) string { + return Realm("").Func(title, fn, args...) +} + +// FuncURL returns a URL for the specified function with optional key-value +// arguments, for the current realm. +func FuncURL(fn string, args ...string) string { + return Realm("").FuncURL(fn, args...) +} + +// Home returns the URL for the help homepage of the current realm. +func Home() string { + return Realm("").Home() +} + +// Realm represents a specific realm for generating help links. +type Realm string + +// prefix returns the URL prefix for the realm. +func (r Realm) prefix() string { + // relative + if r == "" { + return "" + } + + // local realm -> /realm + realm := string(r) + if strings.Contains(realm, chainDomain) { + return strings.TrimPrefix(realm, chainDomain) + } + + // remote realm -> https://remote.land/realm + return "https://" + string(r) +} + +// Func returns a markdown link for the specified function with optional +// key-value arguments. +func (r Realm) Func(title string, fn string, args ...string) string { + // XXX: escape title + return "[" + title + "](" + r.FuncURL(fn, args...) + ")" +} + +// FuncURL returns a URL for the specified function with optional key-value +// arguments. +func (r Realm) FuncURL(fn string, args ...string) string { + tlr := txlink.Realm(r) + return tlr.URL(fn, args...) +} + +// Home returns the base help URL for the specified realm. +func (r Realm) Home() string { + return r.prefix() + "?help" +} diff --git a/examples/gno.land/p/moul/helplink/helplink_test.gno b/examples/gno.land/p/moul/helplink/helplink_test.gno new file mode 100644 index 000000000000..07111158a984 --- /dev/null +++ b/examples/gno.land/p/moul/helplink/helplink_test.gno @@ -0,0 +1,78 @@ +package helplink + +import ( + "testing" + + "gno.land/p/demo/urequire" +) + +func TestFunc(t *testing.T) { + tests := []struct { + title string + fn string + args []string + want string + realm Realm + }{ + {"Example", "foo", []string{"bar", "1", "baz", "2"}, "[Example](?help&__func=foo&bar=1&baz=2)", ""}, + {"Realm Example", "foo", []string{"bar", "1", "baz", "2"}, "[Realm Example](/r/lorem/ipsum?help&__func=foo&bar=1&baz=2)", "gno.land/r/lorem/ipsum"}, + {"Single Arg", "testFunc", []string{"key", "value"}, "[Single Arg](?help&__func=testFunc&key=value)", ""}, + {"No Args", "noArgsFunc", []string{}, "[No Args](?help&__func=noArgsFunc)", ""}, + {"Odd Args", "oddArgsFunc", []string{"key"}, "[Odd Args](?help&__func=oddArgsFunc)", ""}, + } + + for _, tt := range tests { + t.Run(tt.title, func(t *testing.T) { + got := tt.realm.Func(tt.title, tt.fn, tt.args...) + urequire.Equal(t, tt.want, got) + }) + } +} + +func TestFuncURL(t *testing.T) { + tests := []struct { + fn string + args []string + want string + realm Realm + }{ + {"foo", []string{"bar", "1", "baz", "2"}, "?help&__func=foo&bar=1&baz=2", ""}, + {"testFunc", []string{"key", "value"}, "?help&__func=testFunc&key=value", ""}, + {"noArgsFunc", []string{}, "?help&__func=noArgsFunc", ""}, + {"oddArgsFunc", []string{"key"}, "?help&__func=oddArgsFunc", ""}, + {"foo", []string{"bar", "1", "baz", "2"}, "/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.land/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.land/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "/r/lorem/ipsum?help&__func=noArgsFunc", "gno.land/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.land/r/lorem/ipsum"}, + {"foo", []string{"bar", "1", "baz", "2"}, "https://gno.world/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.world/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "https://gno.world/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.world/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "https://gno.world/r/lorem/ipsum?help&__func=noArgsFunc", "gno.world/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "https://gno.world/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.world/r/lorem/ipsum"}, + } + + for _, tt := range tests { + title := tt.fn + t.Run(title, func(t *testing.T) { + got := tt.realm.FuncURL(tt.fn, tt.args...) + urequire.Equal(t, tt.want, got) + }) + } +} + +func TestHome(t *testing.T) { + tests := []struct { + realm Realm + want string + }{ + {"", "?help"}, + {"gno.land/r/lorem/ipsum", "/r/lorem/ipsum?help"}, + {"gno.world/r/lorem/ipsum", "https://gno.world/r/lorem/ipsum?help"}, + } + + for _, tt := range tests { + t.Run(string(tt.realm), func(t *testing.T) { + got := tt.realm.Home() + urequire.Equal(t, tt.want, got) + }) + } +} diff --git a/examples/gno.land/p/moul/txlink/gno.mod b/examples/gno.land/p/moul/txlink/gno.mod new file mode 100644 index 000000000000..6110464316fa --- /dev/null +++ b/examples/gno.land/p/moul/txlink/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/moul/txlink + +require gno.land/p/demo/urequire v0.0.0-latest diff --git a/examples/gno.land/p/moul/txlink/txlink.gno b/examples/gno.land/p/moul/txlink/txlink.gno new file mode 100644 index 000000000000..26656e67f299 --- /dev/null +++ b/examples/gno.land/p/moul/txlink/txlink.gno @@ -0,0 +1,74 @@ +// Package txlink provides utilities for creating transaction-related links +// compatible with Gnoweb, Gnobro, and other clients within the Gno ecosystem. +// +// This package is optimized for generating lightweight transaction links with +// flexible arguments, allowing users to build dynamic links that integrate +// seamlessly with various Gno clients. +// +// The primary function, URL, is designed to produce markdown links for +// transaction functions in the current "relative realm". By specifying a custom +// Realm, you can generate links that either use the current realm path or a +// fully qualified path for another realm. +// +// This package is a streamlined alternative to helplink, providing similar +// functionality for transaction links without the full feature set of helplink. +package txlink + +import ( + "std" + "strings" +) + +const chainDomain = "gno.land" // XXX: std.ChainDomain (#2911) + +// URL returns a URL for the specified function with optional key-value +// arguments, for the current realm. +func URL(fn string, args ...string) string { + return Realm("").URL(fn, args...) +} + +// Realm represents a specific realm for generating tx links. +type Realm string + +// prefix returns the URL prefix for the realm. +func (r Realm) prefix() string { + // relative + if r == "" { + curPath := std.CurrentRealm().PkgPath() + return strings.TrimPrefix(curPath, chainDomain) + } + + // local realm -> /realm + realm := string(r) + if strings.Contains(realm, chainDomain) { + return strings.TrimPrefix(realm, chainDomain) + } + + // remote realm -> https://remote.land/realm + return "https://" + string(r) +} + +// URL returns a URL for the specified function with optional key-value +// arguments. +func (r Realm) URL(fn string, args ...string) string { + // Start with the base query + url := r.prefix() + "?help&__func=" + fn + + // Check if args length is even + if len(args)%2 != 0 { + // If not even, we can choose to handle the error here. + // For example, we can just return the URL without appending + // more args. + return url + } + + // Append key-value pairs to the URL + for i := 0; i < len(args); i += 2 { + key := args[i] + value := args[i+1] + // XXX: escape keys and args + url += "&" + key + "=" + value + } + + return url +} diff --git a/examples/gno.land/p/moul/txlink/txlink_test.gno b/examples/gno.land/p/moul/txlink/txlink_test.gno new file mode 100644 index 000000000000..7a460889148c --- /dev/null +++ b/examples/gno.land/p/moul/txlink/txlink_test.gno @@ -0,0 +1,37 @@ +package txlink + +import ( + "testing" + + "gno.land/p/demo/urequire" +) + +func TestURL(t *testing.T) { + tests := []struct { + fn string + args []string + want string + realm Realm + }{ + {"foo", []string{"bar", "1", "baz", "2"}, "?help&__func=foo&bar=1&baz=2", ""}, + {"testFunc", []string{"key", "value"}, "?help&__func=testFunc&key=value", ""}, + {"noArgsFunc", []string{}, "?help&__func=noArgsFunc", ""}, + {"oddArgsFunc", []string{"key"}, "?help&__func=oddArgsFunc", ""}, + {"foo", []string{"bar", "1", "baz", "2"}, "/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.land/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.land/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "/r/lorem/ipsum?help&__func=noArgsFunc", "gno.land/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.land/r/lorem/ipsum"}, + {"foo", []string{"bar", "1", "baz", "2"}, "https://gno.world/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.world/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "https://gno.world/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.world/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "https://gno.world/r/lorem/ipsum?help&__func=noArgsFunc", "gno.world/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "https://gno.world/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.world/r/lorem/ipsum"}, + } + + for _, tt := range tests { + title := tt.fn + t.Run(title, func(t *testing.T) { + got := tt.realm.URL(tt.fn, tt.args...) + urequire.Equal(t, tt.want, got) + }) + } +} diff --git a/examples/gno.land/r/demo/boards/board.gno b/examples/gno.land/r/demo/boards/board.gno index a9cf56c2a915..79b27da84b28 100644 --- a/examples/gno.land/r/demo/boards/board.gno +++ b/examples/gno.land/r/demo/boards/board.gno @@ -6,6 +6,7 @@ import ( "time" "gno.land/p/demo/avl" + "gno.land/p/moul/txlink" ) //---------------------------------------- @@ -134,7 +135,5 @@ func (board *Board) GetURLFromThreadAndReplyID(threadID, replyID PostID) string } func (board *Board) GetPostFormURL() string { - return "/r/demo/boards?help&__func=CreateThread" + - "&bid=" + board.id.String() + - "&body.type=textarea" + return txlink.URL("CreateThread", "bid", board.id.String()) } diff --git a/examples/gno.land/r/demo/boards/gno.mod b/examples/gno.land/r/demo/boards/gno.mod index 434ad019883b..24fea7ce8530 100644 --- a/examples/gno.land/r/demo/boards/gno.mod +++ b/examples/gno.land/r/demo/boards/gno.mod @@ -2,5 +2,6 @@ module gno.land/r/demo/boards require ( gno.land/p/demo/avl v0.0.0-latest + gno.land/p/moul/txlink v0.0.0-latest gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/boards/post.gno b/examples/gno.land/r/demo/boards/post.gno index f35cf23628ce..95d4b2977bae 100644 --- a/examples/gno.land/r/demo/boards/post.gno +++ b/examples/gno.land/r/demo/boards/post.gno @@ -6,6 +6,7 @@ import ( "time" "gno.land/p/demo/avl" + "gno.land/p/moul/txlink" ) //---------------------------------------- @@ -155,27 +156,26 @@ func (post *Post) GetURL() string { } func (post *Post) GetReplyFormURL() string { - return "/r/demo/boards?help&__func=CreateReply" + - "&bid=" + post.board.id.String() + - "&threadid=" + post.threadID.String() + - "&postid=" + post.id.String() + - "&body.type=textarea" + return txlink.URL("CreateReply", + "bid", post.board.id.String(), + "threadid", post.threadID.String(), + "postid", post.id.String(), + ) } func (post *Post) GetRepostFormURL() string { - return "/r/demo/boards?help&__func=CreateRepost" + - "&bid=" + post.board.id.String() + - "&postid=" + post.id.String() + - "&title.type=textarea" + - "&body.type=textarea" + - "&dstBoardID.type=textarea" + return txlink.URL("CreateRepost", + "bid", post.board.id.String(), + "postid", post.id.String(), + ) } func (post *Post) GetDeleteFormURL() string { - return "/r/demo/boards?help&__func=DeletePost" + - "&bid=" + post.board.id.String() + - "&threadid=" + post.threadID.String() + - "&postid=" + post.id.String() + return txlink.URL("DeletePost", + "bid", post.board.id.String(), + "threadid", post.threadID.String(), + "postid", post.id.String(), + ) } func (post *Post) RenderSummary() string { diff --git a/examples/gno.land/r/demo/boards/z_0_filetest.gno b/examples/gno.land/r/demo/boards/z_0_filetest.gno index e20964d50b7f..cdf136be590b 100644 --- a/examples/gno.land/r/demo/boards/z_0_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_0_filetest.gno @@ -24,7 +24,7 @@ func main() { } // Output: -// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1&body.type=textarea)] +// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1)] // // ---------------------------------------- // ## [First Post (title)](/r/demo/boards:test_board/1) diff --git a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno index 8555af0b5768..cc8d188f7277 100644 --- a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno @@ -35,14 +35,14 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > First reply of the First post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] // // ---------------------------------------------------- // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] diff --git a/examples/gno.land/r/demo/boards/z_10_filetest.gno b/examples/gno.land/r/demo/boards/z_10_filetest.gno index 548b5865f65b..0a4626003d10 100644 --- a/examples/gno.land/r/demo/boards/z_10_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_10_filetest.gno @@ -33,7 +33,7 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // ---------------------------------------------------- // thread does not exist with id: 1 diff --git a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno index c114e769ab10..04dd6bfb547f 100644 --- a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno @@ -35,18 +35,18 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > First reply of the First post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] // // ---------------------------------------------------- // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > Edited: First reply of the First post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] diff --git a/examples/gno.land/r/demo/boards/z_11_filetest.gno b/examples/gno.land/r/demo/boards/z_11_filetest.gno index 4cbdeeca4c3c..0974991b814f 100644 --- a/examples/gno.land/r/demo/boards/z_11_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_filetest.gno @@ -33,10 +33,10 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // ---------------------------------------------------- // # Edited: First Post in (title) // // Edited: Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] diff --git a/examples/gno.land/r/demo/boards/z_12_filetest.gno b/examples/gno.land/r/demo/boards/z_12_filetest.gno index 4ea75b27753d..8ae1c99ffbb7 100644 --- a/examples/gno.land/r/demo/boards/z_12_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_12_filetest.gno @@ -30,7 +30,7 @@ func main() { // Output: // 1 -// \[[post](/r/demo/boards?help&__func=CreateThread&bid=2&body.type=textarea)] +// \[[post](/r/demo/boards?help&__func=CreateThread&bid=2)] // // ---------------------------------------- // Repost: Check this out diff --git a/examples/gno.land/r/demo/boards/z_2_filetest.gno b/examples/gno.land/r/demo/boards/z_2_filetest.gno index f0d53204e389..037a855eab16 100644 --- a/examples/gno.land/r/demo/boards/z_2_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_2_filetest.gno @@ -32,7 +32,7 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] diff --git a/examples/gno.land/r/demo/boards/z_3_filetest.gno b/examples/gno.land/r/demo/boards/z_3_filetest.gno index 021ae10b8257..79770aa1cecf 100644 --- a/examples/gno.land/r/demo/boards/z_3_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_3_filetest.gno @@ -34,7 +34,7 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] diff --git a/examples/gno.land/r/demo/boards/z_4_filetest.gno b/examples/gno.land/r/demo/boards/z_4_filetest.gno index f0620c28c9de..61e4681f202d 100644 --- a/examples/gno.land/r/demo/boards/z_4_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_4_filetest.gno @@ -37,13 +37,13 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // // > Second reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] // Realm: // switchrealm["gno.land/r/demo/users"] diff --git a/examples/gno.land/r/demo/boards/z_5_c_filetest.gno b/examples/gno.land/r/demo/boards/z_5_c_filetest.gno index 176b1d890154..440daa6238d0 100644 --- a/examples/gno.land/r/demo/boards/z_5_c_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_c_filetest.gno @@ -33,7 +33,7 @@ func main() { // # First Post (title) // // Body of the first post. (body) -// \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > Reply of the first post -// > \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] diff --git a/examples/gno.land/r/demo/boards/z_5_filetest.gno b/examples/gno.land/r/demo/boards/z_5_filetest.gno index c326d961c919..9d30d9aaa720 100644 --- a/examples/gno.land/r/demo/boards/z_5_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_filetest.gno @@ -33,11 +33,11 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // // > Second reply of the second post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] diff --git a/examples/gno.land/r/demo/boards/z_6_filetest.gno b/examples/gno.land/r/demo/boards/z_6_filetest.gno index b7de2d08bf90..fb7f9a317722 100644 --- a/examples/gno.land/r/demo/boards/z_6_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_6_filetest.gno @@ -35,15 +35,15 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // > // > > First reply of the first reply // > > -// > > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] +// > > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] // // > Second reply of the second post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] diff --git a/examples/gno.land/r/demo/boards/z_7_filetest.gno b/examples/gno.land/r/demo/boards/z_7_filetest.gno index f1d41aa17230..7df06fd760af 100644 --- a/examples/gno.land/r/demo/boards/z_7_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_7_filetest.gno @@ -22,7 +22,7 @@ func main() { } // Output: -// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1&body.type=textarea)] +// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1)] // // ---------------------------------------- // ## [First Post (title)](/r/demo/boards:test_board/1) diff --git a/examples/gno.land/r/demo/boards/z_8_filetest.gno b/examples/gno.land/r/demo/boards/z_8_filetest.gno index 18ad64083f45..02ce2c4fceff 100644 --- a/examples/gno.land/r/demo/boards/z_8_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_8_filetest.gno @@ -35,10 +35,10 @@ func main() { // _[see thread](/r/demo/boards:test_board/2)_ // // Reply of the second post -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // // _[see all 1 replies](/r/demo/boards:test_board/2/3)_ // // > First reply of the first reply // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] diff --git a/examples/gno.land/r/demo/boards/z_9_filetest.gno b/examples/gno.land/r/demo/boards/z_9_filetest.gno index 10a1444fd35a..823318a5e48c 100644 --- a/examples/gno.land/r/demo/boards/z_9_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_9_filetest.gno @@ -34,4 +34,4 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:second_board/1/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=2&threadid=1&postid=1&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=2&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:second_board/1/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=2&threadid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=2&threadid=1&postid=1)] From cfbaff2affb64bc0317916c302cf1dc3bae4d516 Mon Sep 17 00:00:00 2001 From: Morgan Date: Fri, 25 Oct 2024 16:43:08 -0500 Subject: [PATCH 30/31] ci: benchmark only BenchmarkBenchdata (#3007) A bit radical, but I'm open to other benchmarks we should include. Essentially, in an effort to have a small amount of meaningful benchmarks, I'd like for these to only be those in BenchmarkBenchdata. Yes, I recognize this is tooting my own horn, but I think they are good benchmarks that tell us, overall, if the GnoVM on a few reference programs got slower or faster, and I found them useful in the past while doing manual execution. Most other benchmarks are micro-benchmarks, which aren't likely to change often or to give us useful insight. I'm open to suggestions for others that make sense to be tracked, but I think it's for the better if we keep the number low so the CI for benchmarks can run in just a few minutes. --- .github/workflows/benchmark-master-push.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark-master-push.yml b/.github/workflows/benchmark-master-push.yml index 09978a0ae5c0..bde6e623a88e 100644 --- a/.github/workflows/benchmark-master-push.yml +++ b/.github/workflows/benchmark-master-push.yml @@ -34,9 +34,12 @@ jobs: go-version: "1.22.x" - name: Run benchmark + # add more benchmarks by adding additional lines for different packages; + # or modify the -bench regexp. run: | - go test -benchmem -bench=. ./... -run=^$ \ - -cpu 1,2 -timeout 50m | tee benchmarks.txt + set -xeuo pipefail && ( + go test ./gnovm/pkg/gnolang -bench='BenchmarkBenchdata' -benchmem -run='^$' -v -cpu=1,2 + ) | tee benchmarks.txt - name: Download previous benchmark data uses: actions/cache@v4 From 2838ad1a3c3b9795990257cd46f08fc04b2fb3a3 Mon Sep 17 00:00:00 2001 From: Morgan Date: Fri, 25 Oct 2024 16:45:46 -0500 Subject: [PATCH 31/31] ci: add workflow to ensure go.mod files are tidied (#3025)
    Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests
    --- .github/workflows/mod-tidy.yml | 26 +++++++++++++++++++++++++ tm2/pkg/amino/tests/proto3/proto/doc.go | 3 +++ 2 files changed, 29 insertions(+) create mode 100644 .github/workflows/mod-tidy.yml create mode 100644 tm2/pkg/amino/tests/proto3/proto/doc.go diff --git a/.github/workflows/mod-tidy.yml b/.github/workflows/mod-tidy.yml new file mode 100644 index 000000000000..118761bddf9a --- /dev/null +++ b/.github/workflows/mod-tidy.yml @@ -0,0 +1,26 @@ +name: Ensure go.mods are tidied + +on: + push: + branches: + - master + workflow_dispatch: + pull_request: + +jobs: + main: + name: Ensure go.mods are tidied + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go-version }} + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check go.mod files are up to date + working-directory: ${{ inputs.modulepath }} + run: | + make tidy VERIFY_GO_SUMS=true diff --git a/tm2/pkg/amino/tests/proto3/proto/doc.go b/tm2/pkg/amino/tests/proto3/proto/doc.go new file mode 100644 index 000000000000..909d94e7e7f5 --- /dev/null +++ b/tm2/pkg/amino/tests/proto3/proto/doc.go @@ -0,0 +1,3 @@ +// This file ensures there is at least one go file in this dir at all times. + +package proto3