diff --git a/extension/generator/file.go b/extension/generator/file.go new file mode 100644 index 00000000..85ef2026 --- /dev/null +++ b/extension/generator/file.go @@ -0,0 +1,88 @@ +/* + Copyright 2023 Loophole Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package generator + +import ( + "bytes" + "io" + "io/fs" + "os" + "time" + + "golang.org/x/mod/zip" +) + +var _ zip.File = (*File)(nil) +var _ os.FileInfo = (*File)(nil) + +type File struct { + name string + path string + content []byte + reader *bytes.Reader + size int64 +} + +func NewFile(name string, path string, content []byte) File { + return File{ + name: name, + path: path, + content: content, + reader: bytes.NewReader(content), + size: int64(len(content)), + } +} + +func (g File) Name() string { + return g.name +} + +func (g File) Size() int64 { + return g.size +} + +func (g File) Mode() fs.FileMode { + return 0700 +} + +func (g File) ModTime() time.Time { + return time.Now() +} + +func (g File) IsDir() bool { + return false +} + +func (g File) Sys() any { + return g.content +} + +func (g File) Path() string { + return g.path +} + +func (g File) Lstat() (os.FileInfo, error) { + return g, nil +} + +func (g File) Open() (io.ReadCloser, error) { + return io.NopCloser(g.reader), nil +} + +func (g File) Data() []byte { + return g.content +} diff --git a/extension/generator/generator.go b/extension/generator/generator.go new file mode 100644 index 00000000..b7167b27 --- /dev/null +++ b/extension/generator/generator.go @@ -0,0 +1,135 @@ +/* + Copyright 2023 Loophole Labs + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package generator + +import ( + "bytes" + "encoding/hex" + + "github.com/loopholelabs/scale/extension" + "github.com/loopholelabs/scale/extension/generator/golang" +) + +type GuestRegistryPackage struct { + GolangModule *bytes.Buffer + GolangModfile []byte + RustCrate *bytes.Buffer + RustCargofile []byte + TypescriptPackage *bytes.Buffer + TypescriptPackageJSON []byte +} + +type GuestLocalPackage struct { + GolangFiles []File + RustFiles []File + TypescriptFiles []File +} + +type HostRegistryPackage struct { + GolangModule *bytes.Buffer + GolangModfile []byte + TypescriptPackage *bytes.Buffer + TypescriptPackageJSON []byte +} + +type HostLocalPackage struct { + GolangFiles []File + TypescriptFiles []File +} + +type Options struct { + Extension *extension.Schema + + GolangPackageImportPath string + GolangPackageName string + GolangPackageVersion string +} + +func GenerateGuestLocal(options *Options) (*GuestLocalPackage, error) { + hash, err := options.Extension.Hash() + if err != nil { + return nil, err + } + hashString := hex.EncodeToString(hash) + + golangTypes, err := golang.GenerateTypes(options.Extension, options.GolangPackageName) + if err != nil { + return nil, err + } + + golangGuest, err := golang.GenerateGuest(options.Extension, hashString, options.GolangPackageName) + if err != nil { + return nil, err + } + + golangInterfaces, err := golang.GenerateInterfaces(options.Extension, hashString, options.GolangPackageName) + if err != nil { + return nil, err + } + + modfile, err := golang.GenerateModfile(options.GolangPackageImportPath) + if err != nil { + return nil, err + } + + golangFiles := []File{ + NewFile("types.go", "types.go", golangTypes), + NewFile("guest.go", "guest.go", golangGuest), + NewFile("interfaces.go", "interfaces.go", golangInterfaces), + NewFile("go.mod", "go.mod", modfile), + } + + return &GuestLocalPackage{ + GolangFiles: golangFiles, + }, nil +} + +func GenerateHostLocal(options *Options) (*HostLocalPackage, error) { + hash, err := options.Extension.Hash() + if err != nil { + return nil, err + } + hashString := hex.EncodeToString(hash) + + golangTypes, err := golang.GenerateTypes(options.Extension, options.GolangPackageName) + if err != nil { + return nil, err + } + + golangHost, err := golang.GenerateHost(options.Extension, hashString, options.GolangPackageName) + if err != nil { + return nil, err + } + + golangInterfaces, err := golang.GenerateInterfaces(options.Extension, hashString, options.GolangPackageName) + if err != nil { + return nil, err + } + + modfile, err := golang.GenerateModfile(options.GolangPackageImportPath) + if err != nil { + return nil, err + } + + golangFiles := []File{ + NewFile("types.go", "types.go", golangTypes), + NewFile("host.go", "host.go", golangHost), + NewFile("interfaces.go", "interfaces.go", golangInterfaces), + NewFile("go.mod", "go.mod", modfile), + } + + return &HostLocalPackage{ + GolangFiles: golangFiles, + }, nil +} diff --git a/extension/generator/golang/generator.go b/extension/generator/golang/generator.go index a32e649b..82ea349b 100644 --- a/extension/generator/golang/generator.go +++ b/extension/generator/golang/generator.go @@ -18,8 +18,12 @@ import ( "go/format" "text/template" + polyglotVersion "github.com/loopholelabs/polyglot/version" + interfacesVersion "github.com/loopholelabs/scale-signature-interfaces/version" "github.com/loopholelabs/scale/extension" + scaleVersion "github.com/loopholelabs/scale/version" + "github.com/loopholelabs/scale/extension/generator/templates" "github.com/loopholelabs/scale/signature/generator/utils" ) @@ -30,8 +34,8 @@ const ( var generator *Generator -func Generate(schema *extension.Schema, packageName string, version string) ([]byte, error) { - return generator.Generate(schema, packageName, version) +func GenerateTypes(schema *extension.Schema, packageName string) ([]byte, error) { + return generator.GenerateTypes(schema, packageName) } func GenerateInterfaces(schema *extension.Schema, packageName string, version string) ([]byte, error) { @@ -42,8 +46,8 @@ func GenerateGuest(schema *extension.Schema, packageName string, version string) return generator.GenerateGuest(schema, packageName, version) } -func GenerateModfile(packageName string, polyglotVersion string) ([]byte, error) { - return generator.GenerateModfile(packageName, polyglotVersion) +func GenerateModfile(packageName string) ([]byte, error) { + return generator.GenerateModfile(packageName) } func GenerateHost(schema *extension.Schema, packageName string, version string) ([]byte, error) { @@ -76,16 +80,21 @@ func New() (*Generator, error) { } // Generate generates the go code -func (g *Generator) Generate(schema *extension.Schema, packageName string, version string) ([]byte, error) { +func (g *Generator) GenerateTypes(schema *extension.Schema, packageName string) ([]byte, error) { if packageName == "" { packageName = defaultPackageName } + ext, err := schema.CloneWithDisabledAccessorsValidatorsAndModifiers() + if err != nil { + return nil, err + } + buf := new(bytes.Buffer) - err := g.templ.ExecuteTemplate(buf, "types.go.templ", map[string]any{ - "schema": schema, - "version": version, - "package": packageName, + err = g.templ.ExecuteTemplate(buf, "types.go.templ", map[string]any{ + "signature_schema": ext, + "generator_version": scaleVersion.Version(), + "package_name": packageName, }) if err != nil { return nil, err @@ -132,11 +141,12 @@ func (g *Generator) GenerateGuest(schema *extension.Schema, packageName string, } // GenerateModfile generates the modfile for the signature -func (g *Generator) GenerateModfile(packageName string, polyglotVersion string) ([]byte, error) { +func (g *Generator) GenerateModfile(packageImportPath string) ([]byte, error) { buf := new(bytes.Buffer) err := g.templ.ExecuteTemplate(buf, "mod.go.templ", map[string]any{ - "polyglot_version": polyglotVersion, - "package": packageName, + "polyglot_version": polyglotVersion.Version(), + "scale_signature_interfaces_version": interfacesVersion.Version(), + "package_import_path": packageImportPath, }) if err != nil { return nil, err diff --git a/extension/generator/golang/generator_test.go b/extension/generator/golang/generator_test.go index dd216ec7..6de3c477 100644 --- a/extension/generator/golang/generator_test.go +++ b/extension/generator/golang/generator_test.go @@ -36,7 +36,7 @@ func TestGenerator(t *testing.T) { require.NoError(t, err) os.WriteFile("./interfaces.txt", f_interfaces, 0644) - formatted, err := Generate(s, "types", "v0.1.0") + formatted, err := GenerateTypes(s, "types") require.NoError(t, err) // Check things... @@ -57,7 +57,7 @@ func TestGenerator(t *testing.T) { os.WriteFile("./guest.txt", f_guest, 0644) - modf, err := GenerateModfile(packageName, "v0.1.0") + modf, err := GenerateModfile(packageName) require.NoError(t, err) os.WriteFile("./modfile.txt", modf, 0644) diff --git a/extension/generator/templates/arrays.rs.templ b/extension/generator/templates/arrays.rs.templ deleted file mode 100644 index 2d15e2ad..00000000 --- a/extension/generator/templates/arrays.rs.templ +++ /dev/null @@ -1,37 +0,0 @@ -{{ define "rs_arrays_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - {{ SnakeCase .Name }}: Vec<{{ Primitive $type }}>, - {{- else }} - pub {{ SnakeCase .Name }}: Vec<{{ Primitive $type }}>, - {{- end -}} - {{- end }} -{{ end }} - -{{ define "rs_arrays_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{ SnakeCase .Name }}: Vec::with_capacity({{ .InitialSize }}), - {{- end }} -{{ end }} - -{{ define "rs_arrays_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - e.encode_array(self.{{ SnakeCase .Name }}.len(), {{ PolyglotPrimitive $type }})?; - for a in &self.{{ SnakeCase .Name }} { - e.{{ PolyglotPrimitiveEncode $type }}(*a)?; - } - {{- end }} -{{ end }} - -{{ define "rs_arrays_decode" }} - {{ $type := .Type }} - {{- range .Entries }} - let size_{{ SnakeCase .Name }} = d.decode_array({{ PolyglotPrimitive $type }})?; - for _ in 0..size_{{ SnakeCase .Name }} { - x.{{ SnakeCase .Name }}.push(d.{{ PolyglotPrimitiveDecode $type }}()?); - } - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/arrays.ts.templ b/extension/generator/templates/arrays.ts.templ deleted file mode 100644 index 7bb2126d..00000000 --- a/extension/generator/templates/arrays.ts.templ +++ /dev/null @@ -1,63 +0,0 @@ -{{ define "ts_arrays_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - #{{ CamelCase .Name }}: {{ Primitive $type }}; - {{- else }} - {{ CamelCase .Name }}: {{ Primitive $type }}[]; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_arrays_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = []; - {{- else }} - this.{{ CamelCase .Name }} = []; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_arrays_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - const {{ CamelCase .Name }}Length = this.#{{ CamelCase .Name }}.length; - encoder.array({{ CamelCase .Name }}Length, {{ PolyglotPrimitive $type }}); - - for (let i = 0; i < {{ CamelCase .Name }}Length; i += 1) { - encoder.{{ PolyglotPrimitiveEncode $type }}(this.#{{ CamelCase .Name }}[i]); - } - {{- else }} - const {{ CamelCase .Name }}Length = this.{{ CamelCase .Name }}.length; - encoder.array({{ CamelCase .Name }}Length, {{ PolyglotPrimitive $type }}); - - for (let i = 0; i < {{ CamelCase .Name }}Length; i += 1) { - encoder.{{ PolyglotPrimitiveEncode $type }}(this.{{ CamelCase .Name }}[i]); - } - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_arrays_decode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - const {{ CamelCase .Name }}Size = decoder.array({{ PolyglotPrimitive $type }}); - this.#{{ CamelCase .Name }} = new Array({{ CamelCase .Name }}Size); - - for (let i = 0; i < {{ CamelCase .Name }}Size; i += 1) { - this.#{{ CamelCase .Name }}[i] = decoder.{{ PolyglotPrimitiveDecode $type }}(); - } - {{- else }} - const {{ CamelCase .Name }}Size = decoder.array({{ PolyglotPrimitive $type }}); - this.{{ CamelCase .Name }} = new Array({{ CamelCase .Name }}Size); - - for (let i = 0; i < {{ CamelCase .Name }}Size; i += 1) { - this.{{ CamelCase .Name }}[i] = decoder.{{ PolyglotPrimitiveDecode $type }}(); - } - {{- end -}} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/boilerplate.templ b/extension/generator/templates/boilerplate.templ deleted file mode 100644 index 237b2777..00000000 --- a/extension/generator/templates/boilerplate.templ +++ /dev/null @@ -1,10 +0,0 @@ -version = "v1alpha" -name = "{{ .Name }}" -tag = "{{ .Tag }}" -context = "Default" - -model Default { - string Data { - default = "Hello World" - } -} \ No newline at end of file diff --git a/extension/generator/templates/enumarrays.rs.templ b/extension/generator/templates/enumarrays.rs.templ deleted file mode 100644 index bdd88db9..00000000 --- a/extension/generator/templates/enumarrays.rs.templ +++ /dev/null @@ -1,36 +0,0 @@ -{{ define "rs_enumarrays_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumArrays }} - {{- if (Deref .Accessor) }} - {{ SnakeCase .Name }}: Vec<{{ .Reference }}>, - {{- else }} - pub {{ SnakeCase .Name }}: Vec<{{ .Reference }}>, - {{- end -}} - {{- end }} -{{ end }} - -{{ define "rs_enumarrays_new_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumArrays }} - {{ SnakeCase .Name }}: Vec::with_capacity({{ .InitialSize }}), - {{- end }} -{{ end }} - -{{ define "rs_enumarrays_encode" }} - {{- range .EnumArrays }} - e.encode_array(self.{{ SnakeCase .Name}}.len(), Kind::U32)?; - for a in &self.{{ SnakeCase .Name}} { - e.encode_u32(*a as u32)?; - } - {{- end }} -{{ end }} - -{{ define "rs_enumarrays_decode" }} - {{ $current_model := . }} - {{- range .EnumArrays }} - let size_{{ SnakeCase .Name }} = d.decode_array(Kind::U32)?; - for _ in 0..size_{{ SnakeCase .Name }} { - x.{{ SnakeCase .Name }}.push({{ .Reference }}::try_from(d.decode_u32()?)?); - } - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/enumarrays.ts.templ b/extension/generator/templates/enumarrays.ts.templ deleted file mode 100644 index 81d1ec6d..00000000 --- a/extension/generator/templates/enumarrays.ts.templ +++ /dev/null @@ -1,21 +0,0 @@ -{{ define "ts_enumarrays_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumArrays }} - {{- if (Deref .Accessor) }} - #{{ CamelCase .Name }}: {{ .Reference }}[]; - {{- else }} - {{ CamelCase .Name }}: {{ .Reference }}[]; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_enumarrays_new_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumArrays }} - {{- if .Accessor }} - this.#{{ CamelCase .Name }} = []; - {{- else }} - this.{{ CamelCase .Name }} = []; - {{- end -}} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/enummaps.rs.templ b/extension/generator/templates/enummaps.rs.templ deleted file mode 100644 index ace8824b..00000000 --- a/extension/generator/templates/enummaps.rs.templ +++ /dev/null @@ -1,70 +0,0 @@ -{{ define "rs_enummaps_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumMaps }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - {{ SnakeCase .Name }}: HashMap<{ .Reference }}, {{ Primitive .Value }}>, - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - {{ SnakeCase .Name }}: HashMap<{{ .Reference }}, {{ .Value }}>, - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - pub {{ SnakeCase .Name }}: HashMap<{{ .Reference }}, {{ Primitive .Value }}>, - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - pub {{ SnakeCase .Name }}: HashMap<{{ .Reference }}, {{ .Value }}>, - {{- end }} - {{- end }} -{{ end }} - -{{ define "rs_enummaps_new_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumMaps }} - {{ SnakeCase .Name }}: HashMap::new(), - {{ end }} -{{ end }} - -{{ define "rs_enummaps_encode" }} - {{- range .EnumMaps }} - {{- if IsPrimitive .Value }} - e.encode_map(self.{{ SnakeCase .Name }}.len(), Kind::U32, {{ PolyglotPrimitive .Value }})?; - for (k, v) in &self.{{ SnakeCase .Name }} { - e.encode_u32(*k as u32)?; - {{- if eq .Value "string"}} - e.{{ PolyglotPrimitiveEncode .Value }}(&v)?; - {{- else }} - e.{{ PolyglotPrimitiveEncode .Value }}(v)?; - {{- end }} - } - {{- else }} - e.encode_map(self.{{ SnakeCase .Name }}.len(), Kind::U32, Kind::Any)?; - for (k, v) in &self.{{ SnakeCase .Name }} { - e.encode_u32(*k as u32)?; - v.encode_self(e)?; - } - {{- end }} - {{- end }} -{{ end }} - -{{ define "rs_enummaps_decode" }} - {{ $current_model := . }} - {{- range .EnumMaps }} - {{- if IsPrimitive .Value }} - let size_{{ SnakeCase .Name }} = d.decode_map(Kind::U32, {{ PolyglotPrimitive .Value }})?; - for _ in 0..size_{{ SnakeCase .Name }} { - let k = {{ .Reference }}::try_from(d.decode_u32()?)?; - let v = d.{{ PolyglotPrimitiveDecode .Value }}()?; - x.{{ SnakeCase .Name }}.insert(k, v); - } - {{- else }} - let size_{{ SnakeCase .Name }} = d.decode_map(Kind::U32, Kind::Any)?; - for _ in 0..size_{{ SnakeCase .Name }} { - let k = {{ .Reference }}::try_from(d.decode_u32()?)?; - let v = {{ .Value }}::decode(d)?.ok_or(DecodingError::InvalidMap)?; - x.{{ SnakeCase .Name }}.insert(k, v); - } - {{- end }} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/enummaps.ts.templ b/extension/generator/templates/enummaps.ts.templ deleted file mode 100644 index c0a4a781..00000000 --- a/extension/generator/templates/enummaps.ts.templ +++ /dev/null @@ -1,41 +0,0 @@ -{{ define "ts_enummaps_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumMaps }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - #{{ CamelCase .Name }}: Map<{{ .Reference }}, {{ Primitive .Value }}>; - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - #{{ CamelCase .Name }}: Map<{{ .Reference }}, {{ .Value }}>; - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - {{ CamelCase .Name }}: Map<{{ .Reference }}, {{ Primitive .Value }}>; - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - {{ CamelCase .Name }}: Map<{{ .Reference }}, {{ .Value }}>; - {{- end }} - {{ end }} -{{ end }} - -{{ define "ts_enummaps_new_struct_reference" }} - {{ $current_model := . }} - {{- range .EnumMaps }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - this.#{{ CamelCase .Name }} = new Map<{{ .Reference }}, {{ Primitive .Value }}>(); - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - this.#{{ CamelCase .Name }} = new Map<{{ .Reference }}, {{ .Value }}>(); - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - this.{{ CamelCase .Name }} = new Map<{{ .Reference }}, {{ Primitive .Value }}>(); - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - this.{{ CamelCase .Name }} = new Map<{{ .Reference }}, {{ .Value }}>(); - {{- end }} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/enums.rs.templ b/extension/generator/templates/enums.rs.templ deleted file mode 100644 index 800efa56..00000000 --- a/extension/generator/templates/enums.rs.templ +++ /dev/null @@ -1,58 +0,0 @@ -{{ define "rs_enums_definition" }} - #[derive(Debug, Eq, PartialEq, TryFromPrimitive, Copy, Clone, Hash)] - #[repr(u32)] - pub enum {{ .Name }} { - {{- range $index, $value := .Values }} - {{ $value }} = {{ $index }}, - {{- end }} - } -{{ end }} - -{{ define "rs_enums_struct_reference" }} - {{ $current_model := . }} - {{- range .Enums }} - {{- if (Deref .Accessor) }} - {{ SnakeCase .Name }}: {{ .Reference }}, - {{- else }} - pub {{ SnakeCase .Name }}: {{ .Reference }}, - {{- end -}} - {{ end }} -{{ end }} - -{{ define "rs_enums_new_struct_reference" }} - {{ $current_model := . }} - {{- range .Enums }} - {{ SnakeCase .Name }}: {{ .Reference }}::{{ .Default }}, - {{ end }} -{{ end }} - -{{ define "rs_enums_encode" }} - {{ $current_model := . }} - {{- range .Enums }} - e.encode_u32(self.{{ SnakeCase .Name }} as u32)?; - {{- end }} -{{ end }} - -{{ define "rs_enums_decode" }} - {{ $current_model := . }} - {{- range .Enums }} - x.{{ SnakeCase .Name }} = {{ .Reference }}::try_from(d.decode_u32()?).ok().ok_or(DecodingError::InvalidEnum)?; - {{- end }} -{{ end }} - -{{ define "rs_enums_accessor" }} - {{ $current_model := . }} - {{- range .Enums }} - {{- if .Accessor }} - impl {{ $current_model.Name }} { - pub fn get_{{ SnakeCase .Name }}(&self) -> &{{ .Reference }} { - &self.{{ SnakeCase .Name }} - } - - pub fn set_{{ SnakeCase .Name }}(&mut self, v: {{ .Reference }}) { - self.{{ SnakeCase .Name }} = v; - } - } - {{- end -}} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/enums.ts.templ b/extension/generator/templates/enums.ts.templ deleted file mode 100644 index 4a937314..00000000 --- a/extension/generator/templates/enums.ts.templ +++ /dev/null @@ -1,64 +0,0 @@ -{{ define "ts_enums_definition" }} - export enum {{ .Name }} { - {{- range $index, $value := .Values }} - {{ $value }} = {{ $index }}, - {{ end }} - } -{{ end }} - -{{ define "ts_enums_struct_reference" }} - {{ $current_model := . }} - {{- range .Enums }} - {{- if (Deref .Accessor) }} - #{{ CamelCase .Name }}: {{ .Reference }}; - {{- else }} - {{ CamelCase .Name }}: {{ .Reference }}; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_enums_new_struct_reference" }} - {{ $current_model := . }} - {{- range .Enums }} - {{- if .Accessor }} - this.#{{ CamelCase .Name }} = {{ .Reference }}.{{ .Default }}; - {{- else }} - this.{{ CamelCase .Name }} = {{ .Reference }}.{{ .Default }}; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_enums_encode" }} - {{- range .Enums }} - {{- if (Deref .Accessor) }} - encoder.uint32(this.#{{ CamelCase .Name }}); - {{- else }} - encoder.uint32(this.{{ CamelCase .Name }}); - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_enums_decode" }} - {{- range .Model.Enums }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = decoder.uint32(); - {{- else }} - this.{{ CamelCase .Name }} = decoder.uint32(); - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_enums_accessor" }} - {{ $current_model := . }} - {{- range .Enums }} - {{- if .Accessor }} - get {{ CamelCase .Name }}(): {{ .Reference }} { - return this.#{{ CamelCase .Name }}; - } - - set {{ CamelCase .Name }}(val: {{ .Reference }}) { - this.#{{ CamelCase .Name }} = val; - } - {{- end -}} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/maps.rs.templ b/extension/generator/templates/maps.rs.templ deleted file mode 100644 index d8be9eda..00000000 --- a/extension/generator/templates/maps.rs.templ +++ /dev/null @@ -1,58 +0,0 @@ -{{ define "rs_maps_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - {{ SnakeCase .Name }}: HashMap<{{ Primitive $type }}, {{ Primitive .Value }}>, - {{- else }} - pub {{ SnakeCase .Name }}: HashMap<{{ Primitive $type }}, {{ Primitive .Value }}>, - {{- end }} - {{ end }} -{{ end }} - -{{ define "rs_maps_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{ SnakeCase .Name }}: HashMap::new(), - {{- end }} -{{ end }} - -{{ define "rs_maps_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if IsPrimitive .Value }} - e.encode_map(self.{{ SnakeCase .Name }}.len(), {{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }})?; - for (k, v) in &self.{{ SnakeCase .Name }} { - e.{{ PolyglotPrimitiveEncode $type }}(*k)?; - e.{{ PolyglotPrimitiveEncode .Value }}(*v)?; - } - {{- else }} - e.encode_map(self.{{ SnakeCase .Name }}.len(), {{ PolyglotPrimitive $type }}, Kind::Any)?; - for (k, v) in &self.{{ SnakeCase .Name }} { - e.{{ PolyglotPrimitiveEncode $type }}(*k)?; - v.encode_self(e)?; - } - {{- end }} - - {{- end }} -{{ end }} - -{{ define "rs_maps_decode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if IsPrimitive .Value }} - let size_{{ SnakeCase .Name }} = d.decode_map({{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }})?; - for _ in 0..size_{{ SnakeCase .Name }} { - let k = d.{{ PolyglotPrimitiveDecode $type }}()?; - let v = d.{{ PolyglotPrimitiveDecode .Value }}()?; - x.{{ SnakeCase .Name }}.insert(k, v); - } - {{- else }} - let size_{{ SnakeCase .Name }} = d.decode_map({{ PolyglotPrimitive $type }}, Kind::Any)?; - for _ in 0..size_{{ SnakeCase .Name }} { - let k = d.{{ PolyglotPrimitiveDecode $type }}()?; - let v = {{ .Value }}::decode(d)?.ok_or(DecodingError::InvalidMap)?; - x.{{ SnakeCase .Name }}.insert(k, v); - } - {{- end }} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/maps.ts.templ b/extension/generator/templates/maps.ts.templ deleted file mode 100644 index 4b3a129a..00000000 --- a/extension/generator/templates/maps.ts.templ +++ /dev/null @@ -1,127 +0,0 @@ -{{ define "ts_maps_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - #{{ CamelCase .Name }}: Map<{{ Primitive $type }}, {{ Primitive .Value }}>; - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - #{{ CamelCase .Name }}: Map<{{ Primitive $type }}, {{ .Value }}>; - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - {{ CamelCase .Name }}: Map<{{ Primitive $type }}, {{ Primitive .Value }}>; - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - {{ CamelCase .Name }}: Map<{{ Primitive $type }}, {{ .Value }}>; - {{- end }} - {{ end }} -{{ end }} - -{{ define "ts_maps_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - this.#{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ Primitive .Value }}>(); - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - this.#{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ .Value }}>(); - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - this.{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ Primitive .Value }}>(); - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - this.{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ .Value }}>(); - {{- end }} - {{ end }} -{{ end }} - -{{ define "ts_maps_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - encoder.map(this.#{{ CamelCase .Name }}.size, {{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }}); - this.#{{ CamelCase .Name }}.forEach((val, key) => { - encoder.{{ PolyglotPrimitiveEncode $type }}(key); - encoder.{{ PolyglotPrimitiveEncode .Value }}(val); - }); - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - encoder.map(this.#{{ CamelCase .Name }}.size, {{ PolyglotPrimitive $type }}, Kind.Any); - this.#{{ CamelCase .Name }}.forEach((val, key) => { - encoder.{{ PolyglotPrimitiveEncode $type }}(key); - val.encode(encoder); - }); - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - encoder.map(this.{{ CamelCase .Name }}.size, {{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }}); - this.{{ CamelCase .Name }}.forEach((val, key) => { - encoder.{{ PolyglotPrimitiveEncode $type }}(key); - encoder.{{ PolyglotPrimitiveEncode .Value }}(val); - }); - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - encoder.map(this.{{ CamelCase .Name }}.size, {{ PolyglotPrimitive $type }}, Kind.Any); - this.{{ CamelCase .Name }}.forEach((val, key) => { - encoder.{{ PolyglotPrimitiveEncode $type }}(key); - val.encode(encoder); - }); - {{- end }} - {{ end }} -{{ end }} - -{{ define "ts_maps_decode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if and (Deref .Accessor) (IsPrimitive .Value) }} - this.#{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ Primitive .Value }}>(); - let {{ CamelCase .Name }}Size = decoder.map({{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }}); - for (let i = 0; i < {{ CamelCase .Name }}Size; i++) { - let key = decoder.{{ PolyglotPrimitiveDecode $type }}(); - let val = decoder.{{ PolyglotPrimitiveDecode .Value }}(); - this.#{{ CamelCase .Name }}.set(key, val); - } - {{- end }} - - {{- if and (Deref .Accessor) (not (IsPrimitive .Value)) }} - this.#{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ .Value }}>(); - let {{ CamelCase .Name }}Size = decoder.map({{ PolyglotPrimitive $type }}, Kind.Any); - for (let i = 0; i < {{ CamelCase .Name }}Size; i++) { - let key = decoder.{{ PolyglotPrimitiveDecode $type }}(); - let val = {{ .Value }}.decode(decoder); - if (val !== undefined) { - this.#{{ CamelCase .Name }}.set(key, val); - } - } - {{- end }} - - {{- if and (not (Deref .Accessor)) (IsPrimitive .Value) }} - this.{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ Primitive .Value }}>(); - let {{ CamelCase .Name }}Size = decoder.map({{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }}); - for (let i = 0; i < {{ CamelCase .Name }}Size; i++) { - let key = decoder.{{ PolyglotPrimitiveDecode $type }}(); - let val = decoder.{{ PolyglotPrimitiveDecode .Value }}(); - this.{{ CamelCase .Name }}.set(key, val); - } - {{- end }} - - {{- if and (not (Deref .Accessor)) (not (IsPrimitive .Value)) }} - this.{{ CamelCase .Name }} = new Map<{{ Primitive $type }}, {{ .Value }}>(); - let {{ CamelCase .Name }}Size = decoder.map({{ PolyglotPrimitive $type }}, Kind.Any); - for (let i = 0; i < {{ CamelCase .Name }}Size; i++) { - let key = decoder.{{ PolyglotPrimitiveDecode $type }}(); - let val = {{ .Value }}.decode(decoder); - if (val !== undefined) { - this.{{ CamelCase .Name }}.set(key, val); - } - } - {{- end }} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/mod.go.templ b/extension/generator/templates/mod.go.templ index 47520323..7c330a0c 100644 --- a/extension/generator/templates/mod.go.templ +++ b/extension/generator/templates/mod.go.templ @@ -1,5 +1,8 @@ -module {{ .package }} +module {{ .package_import_path }} go 1.20 -require github.com/loopholelabs/polyglot {{ .polyglot_version }} \ No newline at end of file +require ( + github.com/loopholelabs/polyglot {{ .polyglot_version }} + github.com/loopholelabs/scale-signature-interfaces {{ .scale_signature_interfaces_version }} +) \ No newline at end of file diff --git a/extension/generator/templates/modelarrays.rs.templ b/extension/generator/templates/modelarrays.rs.templ deleted file mode 100644 index af3746aa..00000000 --- a/extension/generator/templates/modelarrays.rs.templ +++ /dev/null @@ -1,50 +0,0 @@ -{{ define "rs_modelarrays_struct_reference" }} - {{- range .ModelArrays }} - {{- if .Accessor }} - {{ SnakeCase .Name }}: Vec<{{ .Reference }}>, - {{- else }} - pub {{ SnakeCase .Name }}: Vec<{{ .Reference }}>, - {{- end -}} - {{ end }} -{{ end }} - -{{ define "rs_modelarrays_new_struct_reference" }} - {{- range .ModelArrays }} - {{ SnakeCase .Name }}: Vec::with_capacity({{ .InitialSize }}), - {{- end }} -{{ end }} - -{{ define "rs_modelarrays_encode" }} - {{- range .ModelArrays }} - e.encode_array(self.{{ SnakeCase .Name }}.len(), Kind::Any)?; - for a in &self.{{ SnakeCase .Name }} { - a.encode_self(e)?; - } - {{- end }} -{{ end }} - -{{ define "rs_modelarrays_decode" }} - {{- range .ModelArrays }} - let size_{{ SnakeCase .Name }} = d.decode_array(Kind::Any)?; - for _ in 0..size_{{ SnakeCase .Name }} { - x.{{ SnakeCase .Name }}.push({{ .Reference }}::decode(d)?.ok_or(DecodingError::InvalidArray)?); - } - {{- end }} -{{ end }} - -{{ define "rs_modelarrays_accessor" }} - {{ $current_model := . }} - {{- range .ModelArrays }} - {{- if .Accessor }} - impl {{ $current_model.Name }} { - pub fn get_{{ SnakeCase .Name }} (&self) -> Option<&Vec<{{ .Reference }}>> { - Some(&self.{{ SnakeCase .Name }}) - } - - pub fn set_{{ SnakeCase .Name }} (&mut self, v: Vec<{{ .Reference }}>) { - self.{{ SnakeCase .Name }} = v; - } - } - {{- end -}} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/modelarrays.ts.templ b/extension/generator/templates/modelarrays.ts.templ deleted file mode 100644 index 18962cf3..00000000 --- a/extension/generator/templates/modelarrays.ts.templ +++ /dev/null @@ -1,80 +0,0 @@ -{{ define "ts_modelarrays_struct_reference" }} - {{- range .ModelArrays }} - {{- if .Accessor }} - #{{ CamelCase .Name }}: Array<{{ .Reference }}>; - {{- else }} - {{ CamelCase .Name }}: Array<{{ .Reference }}>; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_modelarrays_new_struct_reference" }} - {{- range .ModelArrays }} - {{- if .Accessor }} - this.#{{ CamelCase .Name }} = []; - {{- else }} - this.{{ CamelCase .Name }} = []; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_modelarrays_encode" }} - {{- range .ModelArrays }} - {{- if .Accessor }} - const {{ CamelCase .Name }}Length = this.#{{ CamelCase .Name }}.length; - encoder.array({{ CamelCase .Name }}Length, Kind.Any); - for (let i = 0; i < {{ CamelCase .Name }}Length; i += 1) { - let el = this.#{{ CamelCase .Name }}[i]; - el.encode(encoder); - } - {{- else }} - const {{ CamelCase .Name }}Length = this.{{ CamelCase .Name }}.length; - encoder.array({{ CamelCase .Name }}Length, Kind.Any); - for (let i = 0; i < {{ CamelCase .Name }}Length; i += 1) { - let el = this.{{ CamelCase .Name }}[i]; - el.encode(encoder); - } - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_modelarrays_decode" }} - {{- range .ModelArrays }} - {{- if .Accessor }} - const {{ CamelCase .Name }}Size = decoder.array(Kind.Any); - this.#{{ CamelCase .Name }} = new Array({{ CamelCase .Name }}Size); - - for (let i = 0; i < {{ CamelCase .Name }}Size; i += 1) { - const x = {{ .Reference }}.decode(decoder); - if (x !== undefined) { - this.#{{ CamelCase .Name }}[i] = x; - } - } - {{- else }} - const {{ CamelCase .Name }}Size = decoder.array(Kind.Any); - this.{{ CamelCase .Name }} = new Array({{ CamelCase .Name }}Size); - - for (let i = 0; i < {{ CamelCase .Name }}Size; i += 1) { - const x = {{ .Reference }}.decode(decoder); - if (x !== undefined) { - this.{{ CamelCase .Name }}[i] = x; - } - } - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_modelarrays_accessor" }} - {{ $current_model := . }} - {{- range .ModelArrays }} - {{- if .Accessor }} - get {{ CamelCase .Name }}(): Array<{{ .Reference }}> { - return this.#{{ CamelCase .Name }}; - } - - set {{.Name }}(val: Array<{{ .Reference }}>) { - this.#{{ CamelCase .Name }} = val; - } - {{- end -}} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/models.rs.templ b/extension/generator/templates/models.rs.templ deleted file mode 100644 index c1334abd..00000000 --- a/extension/generator/templates/models.rs.templ +++ /dev/null @@ -1,44 +0,0 @@ -{{ define "rs_models_struct_reference" }} - {{- range .Models }} - {{- if .Accessor }} - {{ SnakeCase .Name }}: Option<{{ .Reference }}>, - {{- else }} - pub {{ SnakeCase .Name }}: Option<{{ .Reference }}>, - {{- end -}} - {{- end }} -{{ end }} - -{{ define "rs_models_new_struct_reference" }} - {{- range .Models }} - {{ SnakeCase .Name }}: Some({{ .Reference }}::new()), - {{- end }} -{{ end }} - -{{ define "rs_models_encode" }} - {{- range .Models }} - self.{{ SnakeCase .Name }}.encode_self(e)?; - {{- end }} -{{ end }} - -{{ define "rs_models_decode" }} - {{- range .Models }} - x.{{ SnakeCase .Name }} = {{ .Reference }}::decode(d)?; - {{- end }} -{{ end }} - -{{ define "rs_models_accessor" }} - {{ $current_model := . }} - {{- range .Models }} - {{- if .Accessor }} - impl {{ $current_model.Name }} { - pub fn get_{{ SnakeCase .Name }}(&self) -> &Option<{{ .Reference }}> { - &self.{{ SnakeCase .Name }} - } - - pub fn set_{{ SnakeCase .Name }}(&mut self, v: Option<{{ .Reference }}>) { - self.{{ SnakeCase .Name }} = v; - } - } - {{- end -}} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/models.ts.templ b/extension/generator/templates/models.ts.templ deleted file mode 100644 index 4ce2d7b5..00000000 --- a/extension/generator/templates/models.ts.templ +++ /dev/null @@ -1,62 +0,0 @@ -{{ define "ts_models_struct_reference" }} - {{- range .Models }} - {{- if .Accessor }} - #{{ CamelCase .Name }}: {{ .Reference }} | undefined; - {{- else }} - {{ CamelCase .Name }}: {{ .Reference }} | undefined; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_models_new_struct_reference" }} - {{- range .Models }} - {{- if .Accessor }} - this.#{{ CamelCase .Name }} = new {{ .Reference }}(); - {{- else }} - this.{{ CamelCase .Name }} = new {{ .Reference }}(); - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_models_encode" }} - {{- range .Models }} - {{- if .Accessor }} - if (this.#{{ CamelCase .Name }} === undefined) { - encoder.null(); - } else { - this.#{{ CamelCase .Name }}.encode(encoder); - } - {{- else }} - if (this.{{ CamelCase .Name }} === undefined) { - encoder.null(); - } else { - this.{{ CamelCase .Name }}.encode(encoder); - } - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_models_decode" }} - {{- range .Models }} - {{- if .Accessor }} - this.#{{ CamelCase .Name }} = {{ .Reference }}.decode(decoder); - {{- else }} - this.{{ CamelCase .Name }} = {{ .Reference }}.decode(decoder); - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_models_accessor" }} - {{ $current_model := . }} - {{- range .Models }} - {{- if .Accessor }} - get {{ CamelCase .Name }}(): {{ .Reference }} | undefined { - return this.#{{ CamelCase .Name }}; - } - - set {{ CamelCase .Name }}(val: {{ .Reference }} | undefined) { - this.#{{ CamelCase .Name }} = val; - } - {{- end -}} - {{ end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/primitives.rs.templ b/extension/generator/templates/primitives.rs.templ deleted file mode 100644 index 6d6d4c73..00000000 --- a/extension/generator/templates/primitives.rs.templ +++ /dev/null @@ -1,90 +0,0 @@ -{{ define "rs_primitives_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - {{ SnakeCase .Name }}: {{ Primitive $type }}, - {{- else }} - pub {{ SnakeCase .Name }}: {{ Primitive $type }}, - {{- end -}} - {{ end }} -{{ end }} - -{{ define "rs_primitives_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{ SnakeCase .Name }}: {{ .Default }}, - {{ end }} -{{ end }} - -{{ define "rs_strings_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{ SnakeCase .Name }}: "{{ .Default }}".to_string(), - {{ end }} -{{ end }} - -{{ define "rs_bytes_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{ SnakeCase .Name }}: Vec::with_capacity({{ .InitialSize }}), - {{ end }} -{{ end }} - -{{ define "rs_primitives_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - e.{{ PolyglotPrimitiveEncode $type }}(self.{{ SnakeCase .Name }})?; - {{- end }} -{{ end}} - -{{ define "rs_ref_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - e.{{ PolyglotPrimitiveEncode $type }}(&self.{{ SnakeCase .Name }})?; - {{- end }} -{{ end}} - -{{ define "rs_primitives_decode" }} - {{ $type := .Type }} - {{- range .Entries }} - x.{{ SnakeCase .Name }} = d.{{ PolyglotPrimitiveDecode $type }}()?; - {{- end }} -{{ end}} - -{{ define "rs_numbers_accessor" }} - {{ $type := .Type }} - {{ $model := .Model }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - pub fn get_{{ SnakeCase .Name }}(&self) -> {{ Primitive $type }} { - self.{{ SnakeCase .Name }} - } - - pub fn set_{{ SnakeCase .Name }}(&mut self, v: {{ Primitive $type }}) -> Result<(), Box> { - {{- template "rs_numbers_limit_validator" .LimitValidator }} - self.{{ SnakeCase .Name }} = v; - Ok(()) - } - {{- end -}} - {{ end }} -{{ end }} - -{{ define "rs_strings_accessor" }} - {{ $type := .Type }} - {{ $model := .Model }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - pub fn get_{{ SnakeCase .Name }}(&self) -> {{ Primitive $type }} { - self.{{ SnakeCase .Name }}.clone() - } - - pub fn set_{{ SnakeCase .Name }}(&mut self, mut v: {{ Primitive $type }}) -> Result<(), Box> { - {{- template "rs_regex_validator" .RegexValidator }} - {{- template "rs_length_validator" .LengthValidator }} - {{- template "rs_case_modifier" .CaseModifier }} - self.{{ SnakeCase .Name }} = v; - Ok(()) - } - {{- end -}} - {{ end }} -{{ end }} diff --git a/extension/generator/templates/primitives.ts.templ b/extension/generator/templates/primitives.ts.templ deleted file mode 100644 index 5a17bd04..00000000 --- a/extension/generator/templates/primitives.ts.templ +++ /dev/null @@ -1,112 +0,0 @@ -{{ define "ts_primitives_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - #{{ CamelCase .Name }}: {{ Primitive $type }}; - {{- else }} - {{ CamelCase .Name }}: {{ Primitive $type }}; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_primitives_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = {{ .Default }}; - {{- else }} - this.{{ CamelCase .Name }} = {{ .Default }}; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_strings_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = "{{ .Default }}"; - {{- else }} - this.{{ CamelCase .Name }} = "{{ .Default }}"; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_bigint_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = {{ .Default }}n; - {{- else }} - this.{{ CamelCase .Name }} = {{ .Default }}n; - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_bytes_new_struct_reference" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = new Uint8Array({{ .InitialSize }}); - {{- else }} - this.{{ CamelCase .Name }} = new Uint8Array({{ .InitialSize }}); - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_primitives_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - encoder.{{ PolyglotPrimitiveEncode $type }}(this.#{{ CamelCase .Name }}); - {{- else }} - encoder.{{ PolyglotPrimitiveEncode $type }}(this.{{ CamelCase .Name }}); - {{- end -}} - {{ end }} -{{ end}} - -{{ define "ts_primitives_decode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - this.#{{ CamelCase .Name }} = decoder.{{ PolyglotPrimitiveDecode $type }}(); - {{- else }} - this.{{ CamelCase .Name }} = decoder.{{ PolyglotPrimitiveDecode $type }}(); - {{- end -}} - {{ end }} -{{ end}} - -{{ define "ts_numbers_accessor" }} - {{ $type := .Type }} - {{ $model := .Model }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - get {{ CamelCase .Name }} () { - return this.#{{ CamelCase .Name }}; - } - - set {{ CamelCase .Name }} (val) { - {{- template "ts_numbers_limit_validator" .LimitValidator }} - this.#{{ CamelCase .Name }} = val; - } - {{- end -}} - {{ end }} -{{ end }} - -{{ define "ts_strings_accessor" }} - {{ $type := .Type }} - {{ $model := .Model }} - {{- range .Entries }} - {{- if (Deref .Accessor) }} - get {{ CamelCase .Name }}(): {{ Primitive $type }} { - return this.#{{ CamelCase .Name }}; - } - - set {{ CamelCase .Name }}(val) { - {{- template "ts_regex_validator" .RegexValidator }} - {{- template "ts_length_validator" .LengthValidator }} - {{- template "ts_case_modifier" .CaseModifier }} - this.#{{ CamelCase .Name }} = val; - } - {{- end -}} - {{ end }} -{{ end }} diff --git a/extension/generator/templates/refarrays.rs.templ b/extension/generator/templates/refarrays.rs.templ deleted file mode 100644 index bfa6067b..00000000 --- a/extension/generator/templates/refarrays.rs.templ +++ /dev/null @@ -1,9 +0,0 @@ -{{ define "rs_refarrays_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - e.encode_array(self.{{ SnakeCase .Name }}.len(), {{ PolyglotPrimitive $type }})?; - for a in &self.{{ SnakeCase .Name }} { - e.{{ PolyglotPrimitiveEncode $type }}(&a)?; - } - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/refmaps.rs.templ b/extension/generator/templates/refmaps.rs.templ deleted file mode 100644 index cb53ca9f..00000000 --- a/extension/generator/templates/refmaps.rs.templ +++ /dev/null @@ -1,19 +0,0 @@ -{{ define "rs_refmaps_encode" }} - {{ $type := .Type }} - {{- range .Entries }} - {{- if IsPrimitive .Value }} - e.encode_map(self.{{ SnakeCase .Name }}.len(), {{ PolyglotPrimitive $type }}, {{ PolyglotPrimitive .Value }})?; - for (k, v) in &self.{{ SnakeCase .Name }} { - e.{{ PolyglotPrimitiveEncode $type }}(&k)?; - e.{{ PolyglotPrimitiveEncode .Value }}(&v)?; - } - {{- else }} - e.encode_map(self.{{ SnakeCase .Name }}.len(), {{ PolyglotPrimitive $type }}, Kind::Any)?; - for (k, v) in &self.{{ SnakeCase .Name }} { - e.{{ PolyglotPrimitiveEncode $type }}(&k)?; - v.encode_self(e)?; - } - {{- end }} - - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/types.go.templ b/extension/generator/templates/types.go.templ index 3d672931..27be5545 100644 --- a/extension/generator/templates/types.go.templ +++ b/extension/generator/templates/types.go.templ @@ -1,15 +1,14 @@ -// Code generated by scale-signature-go {{ .version }}, DO NOT EDIT. -// schema: {{ .schema.Name }}:{{ .schema.Tag }} -// output: {{ .package }} +// Code generated by scale-signature {{ .generator_version }}, DO NOT EDIT. +// output: {{ .package_name }} -package {{ .package }} +package {{ .package_name }} import ( "github.com/loopholelabs/polyglot" "errors" - {{ if or (.schema.HasLengthValidator) (.schema.HasRegexValidator) (.schema.HasLimitValidator) }}"fmt"{{ end }} - {{ if .schema.HasRegexValidator }}"regexp"{{ end }} - {{ if .schema.HasCaseModifier }}"strings"{{ end }} + {{ if or (.signature_schema.HasLengthValidator) (.signature_schema.HasRegexValidator) (.signature_schema.HasLimitValidator) }}"fmt"{{ end }} + {{ if .signature_schema.HasRegexValidator }}"regexp"{{ end }} + {{ if .signature_schema.HasCaseModifier }}"strings"{{ end }} ) var ( @@ -17,12 +16,12 @@ var ( InvalidEnum = errors.New("invalid enum value") ) -{{ range .schema.Enums }} +{{ range .signature_schema.Enums }} {{ template "go_enums_definition" . }} {{- end }} -{{- $allEnums := .schema.Enums }} +{{- $allEnums := .signature_schema.Enums }} -{{- range .schema.Models -}} +{{- range .signature_schema.Models -}} {{- if .Description }} // {{ .Name }}: {{ .Description }} {{ end -}} diff --git a/extension/generator/templates/types.rs.templ b/extension/generator/templates/types.rs.templ deleted file mode 100644 index c6fa6c42..00000000 --- a/extension/generator/templates/types.rs.templ +++ /dev/null @@ -1,255 +0,0 @@ -// Code generated by scale-signature-rs {{ .version }}, DO NOT EDIT. -// schema: {{ .schema.Name }}:{{ .schema.Tag }} -// output: {{ .package }} - -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(unused_mut)] - -use std::io::Cursor; -use polyglot_rs::{DecodingError, Encoder, Decoder, Kind}; -use num_enum::TryFromPrimitive; -use std::convert::TryFrom; -use std::collections::HashMap; -use regex::Regex; - -pub trait Encode { - fn encode<'a> (a: &Option, b: &'a mut Cursor>) -> Result<&'a mut Cursor>, Box> where Self: Sized; -} - -trait EncodeSelf { - fn encode_self<'a, 'b> (&'b self, b: &'a mut Cursor>) -> Result<&'a mut Cursor>, Box>; -} - -pub trait Decode { - fn decode (b: &mut Cursor<&mut Vec>) -> Result, Box> where Self: Sized; -} - -{{- range .schema.Enums }} - {{ template "rs_enums_definition" . }} -{{- end }} - -{{- range .schema.Models -}} - {{- if .Description }} - // {{ .Name }}: {{ .Description }} - {{ end -}} - - #[derive(Clone, Debug, PartialEq)] - pub struct {{ .Name }} { - {{ template "rs_models_struct_reference" . }} - {{ template "rs_modelarrays_struct_reference" . }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Strings "Type" "string" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .StringArrays "Type" "string" }} - {{ template "rs_maps_struct_reference" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Int32s "Type" "int32" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "rs_maps_struct_reference" Params "Entries" .Int32Maps "Type" "int32" }} - - - {{ template "rs_primitives_struct_reference" Params "Entries" .Int64s "Type" "int64" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "rs_maps_struct_reference" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Uint32s "Type" "uint32" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "rs_maps_struct_reference" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Uint64s "Type" "uint64" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "rs_maps_struct_reference" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Float32s "Type" "float32" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Float64s "Type" "float64" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "rs_enums_struct_reference" . }} - {{ template "rs_enumarrays_struct_reference" . }} - {{ template "rs_enummaps_struct_reference" . }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "rs_primitives_struct_reference" Params "Entries" .Bools "Type" "bool" }} - {{ template "rs_arrays_struct_reference" Params "Entries" .BoolArrays "Type" "bool" }} - } - - impl {{ .Name }} { - pub fn new () -> Self { - Self { - {{ template "rs_models_new_struct_reference" . }} - {{ template "rs_modelarrays_new_struct_reference" . }} - - {{ template "rs_strings_new_struct_reference" Params "Entries" .Strings }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .StringArrays "Type" "string" }} - {{ template "rs_maps_new_struct_reference" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Int32s }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "rs_maps_new_struct_reference" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Int64s }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "rs_maps_new_struct_reference" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Uint32s }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "rs_maps_new_struct_reference" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Uint64s }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "rs_maps_new_struct_reference" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Float32s }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Float64s }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "rs_enums_new_struct_reference" . }} - {{ template "rs_enumarrays_new_struct_reference" . }} - {{ template "rs_enummaps_new_struct_reference" . }} - - {{ template "rs_bytes_new_struct_reference" Params "Entries" .Bytes }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "rs_primitives_new_struct_reference" Params "Entries" .Bools }} - {{ template "rs_arrays_new_struct_reference" Params "Entries" .BoolArrays "Type" "bool" }} - } - } - - - {{ template "rs_strings_accessor" Params "Model" . "Entries" .Strings "Type" "string" }} - {{ template "rs_numbers_accessor" Params "Model" . "Entries" .Int32s "Type" "int32" }} - {{ template "rs_numbers_accessor" Params "Model" . "Entries" .Int64s "Type" "int64" }} - {{ template "rs_numbers_accessor" Params "Model" . "Entries" .Uint32s "Type" "uint32" }} - {{ template "rs_numbers_accessor" Params "Model" . "Entries" .Uint64s "Type" "uint64" }} - {{ template "rs_numbers_accessor" Params "Model" . "Entries" .Float32s "Type" "float32" }} - {{ template "rs_numbers_accessor" Params "Model" . "Entries" .Float64s "Type" "float32" }} - } - - impl Encode for {{ .Name }} { - fn encode<'a> (a: &Option<{{ .Name }}>, e: &'a mut Cursor>) -> Result<&'a mut Cursor>, Box> { - a.encode_self(e) - } - } - - impl EncodeSelf for {{ .Name }} { - fn encode_self<'a, 'b> (&'b self, e: &'a mut Cursor>) -> Result<&'a mut Cursor>, Box> { - {{ template "rs_models_encode" . }} - {{ template "rs_modelarrays_encode" . }} - - {{ template "rs_ref_encode" Params "Entries" .Strings "Type" "string" }} - {{ template "rs_refarrays_encode" Params "Entries" .StringArrays "Type" "string" }} - {{ template "rs_refmaps_encode" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "rs_primitives_encode" Params "Entries" .Int32s "Type" "int32" }} - {{ template "rs_arrays_encode" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "rs_maps_encode" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "rs_primitives_encode" Params "Entries" .Int64s "Type" "int64" }} - {{ template "rs_arrays_encode" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "rs_maps_encode" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "rs_primitives_encode" Params "Entries" .Uint32s "Type" "uint32" }} - {{ template "rs_arrays_encode" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "rs_maps_encode" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "rs_primitives_encode" Params "Entries" .Uint64s "Type" "uint64" }} - {{ template "rs_arrays_encode" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "rs_maps_encode" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "rs_primitives_encode" Params "Entries" .Float32s "Type" "float32" }} - {{ template "rs_arrays_encode" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "rs_primitives_encode" Params "Entries" .Float64s "Type" "float64" }} - {{ template "rs_arrays_encode" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "rs_enums_encode" . }} - {{ template "rs_enumarrays_encode" . }} - {{ template "rs_enummaps_encode" . }} - - {{ template "rs_ref_encode" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "rs_refarrays_encode" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "rs_primitives_encode" Params "Entries" .Bools "Type" "bool" }} - {{ template "rs_arrays_encode" Params "Entries" .BoolArrays "Type" "bool" }} - - Ok(e) - } - } - - impl EncodeSelf for Option<{{ .Name }}> { - fn encode_self<'a, 'b> (&'b self, e: &'a mut Cursor>) -> Result<&'a mut Cursor>, Box> { - if let Some(x) = self { - x.encode_self(e)?; - } else { - e.encode_none()?; - } - Ok(e) - } - } - - impl Decode for {{ .Name }} { - fn decode (d: &mut Cursor<&mut Vec>) -> Result, Box> { - if d.decode_none() { - return Ok(None); - } - - if let Ok(error) = d.decode_error() { - return Err(error); - } - - let mut x = {{ .Name }}::new(); - - {{ template "rs_models_decode" . }} - {{ template "rs_modelarrays_decode" . }} - - {{ template "rs_primitives_decode" Params "Entries" .Strings "Type" "string" }} - {{ template "rs_arrays_decode" Params "Entries" .StringArrays "Type" "string" }} - {{ template "rs_maps_decode" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "rs_primitives_decode" Params "Entries" .Int32s "Type" "int32" }} - {{ template "rs_arrays_decode" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "rs_maps_decode" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "rs_primitives_decode" Params "Entries" .Int64s "Type" "int64" }} - {{ template "rs_arrays_decode" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "rs_maps_decode" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "rs_primitives_decode" Params "Entries" .Uint32s "Type" "uint32" }} - {{ template "rs_arrays_decode" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "rs_maps_decode" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "rs_primitives_decode" Params "Entries" .Uint64s "Type" "uint64" }} - {{ template "rs_arrays_decode" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "rs_maps_decode" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "rs_primitives_decode" Params "Entries" .Float32s "Type" "float32" }} - {{ template "rs_arrays_decode" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "rs_primitives_decode" Params "Entries" .Float64s "Type" "float64" }} - {{ template "rs_arrays_decode" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "rs_enums_decode" . }} - {{ template "rs_enumarrays_decode" . }} - {{ template "rs_enummaps_decode" . }} - - {{ template "rs_primitives_decode" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "rs_arrays_decode" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "rs_primitives_decode" Params "Entries" .Bools "Type" "bool" }} - {{ template "rs_arrays_decode" Params "Entries" .BoolArrays "Type" "bool" }} - - Ok(Some(x)) - } - } - - {{ template "rs_models_accessor" . }} - {{ template "rs_modelarrays_accessor" . }} - {{ template "rs_enums_accessor" . }} -{{ end -}} \ No newline at end of file diff --git a/extension/generator/templates/types.ts.templ b/extension/generator/templates/types.ts.templ deleted file mode 100644 index b6930dc8..00000000 --- a/extension/generator/templates/types.ts.templ +++ /dev/null @@ -1,219 +0,0 @@ -// Code generated by scale-signature-ts {{ .version }}, DO NOT EDIT. -// schema: {{ .schema.Name }}:{{ .schema.Tag }} -// output: {{ .package }} - -import { Encoder, Decoder, Kind } from "@loopholelabs/polyglot" - -{{ range .schema.Enums }} - {{ template "ts_enums_definition" . }} -{{- end }} -{{- $allEnums := .schema.Enums }} - -{{- range .schema.Models -}} - {{- if .Description }} - // {{ .Name }}: {{ .Description }} - {{ end -}} - - export class {{ .Name }} { - {{ template "ts_models_struct_reference" . }} - {{ template "ts_modelarrays_struct_reference" . }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Strings "Type" "string" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .StringArrays "Type" "string" }} - {{ template "ts_maps_struct_reference" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Int32s "Type" "int32" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "ts_maps_struct_reference" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Int64s "Type" "int64" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "ts_maps_struct_reference" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Uint32s "Type" "uint32" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "ts_maps_struct_reference" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Uint64s "Type" "uint64" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "ts_maps_struct_reference" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Float32s "Type" "float32" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Float64s "Type" "float64" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "ts_enums_struct_reference" . }} - {{ template "ts_enumarrays_struct_reference" . }} - {{ template "ts_enummaps_struct_reference" . }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "ts_primitives_struct_reference" Params "Entries" .Bools "Type" "bool" }} - {{ template "ts_arrays_struct_reference" Params "Entries" .BoolArrays "Type" "bool" }} - - - /** - * @throws {Error} - */ - constructor (decoder?: Decoder) { - if (decoder) { - {{ template "ts_models_decode" . }} - {{ template "ts_modelarrays_decode" . }} - - {{ template "ts_primitives_decode" Params "Entries" .Strings "Type" "string" }} - {{ template "ts_arrays_decode" Params "Entries" .StringArrays "Type" "string" }} - {{ template "ts_maps_decode" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "ts_primitives_decode" Params "Entries" .Int32s "Type" "int32" }} - {{ template "ts_arrays_decode" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "ts_maps_decode" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "ts_primitives_decode" Params "Entries" .Int64s "Type" "int64" }} - {{ template "ts_arrays_decode" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "ts_maps_decode" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "ts_primitives_decode" Params "Entries" .Uint32s "Type" "uint32" }} - {{ template "ts_arrays_decode" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "ts_maps_decode" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "ts_primitives_decode" Params "Entries" .Uint64s "Type" "uint64" }} - {{ template "ts_arrays_decode" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "ts_maps_decode" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "ts_primitives_decode" Params "Entries" .Float32s "Type" "float32" }} - {{ template "ts_arrays_decode" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "ts_primitives_decode" Params "Entries" .Float64s "Type" "float64" }} - {{ template "ts_arrays_decode" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "ts_primitives_decode" Params "Entries" .Enums "Type" "uint32" }} - {{ template "ts_arrays_decode" Params "Entries" .EnumArrays "Type" "uint32" }} - {{ template "ts_maps_decode" Params "Entries" .EnumMaps "Type" "uint32" }} - - {{ template "ts_primitives_decode" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "ts_arrays_decode" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "ts_primitives_decode" Params "Entries" .Bools "Type" "bool" }} - {{ template "ts_arrays_decode" Params "Entries" .BoolArrays "Type" "bool" }} - } else { - {{ template "ts_models_new_struct_reference" . }} - {{ template "ts_modelarrays_new_struct_reference" . }} - - {{ template "ts_strings_new_struct_reference" Params "Entries" .Strings }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .StringArrays "Type" "string" }} - {{ template "ts_maps_new_struct_reference" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "ts_primitives_new_struct_reference" Params "Entries" .Int32s }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "ts_maps_new_struct_reference" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "ts_bigint_new_struct_reference" Params "Entries" .Int64s }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "ts_maps_new_struct_reference" Params "Entries" .Int64Maps "Type" "int64" }} - - - {{ template "ts_primitives_new_struct_reference" Params "Entries" .Uint32s }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "ts_maps_new_struct_reference" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "ts_bigint_new_struct_reference" Params "Entries" .Uint64s }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "ts_maps_new_struct_reference" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "ts_primitives_new_struct_reference" Params "Entries" .Float32s }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "ts_primitives_new_struct_reference" Params "Entries" .Float64s }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "ts_enums_new_struct_reference" . }} - {{ template "ts_enumarrays_new_struct_reference" . }} - {{ template "ts_enummaps_new_struct_reference" . }} - - {{ template "ts_bytes_new_struct_reference" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "ts_primitives_new_struct_reference" Params "Entries" .Bools }} - {{ template "ts_arrays_new_struct_reference" Params "Entries" .BoolArrays "Type" "bool" }} - } - } - - {{ template "ts_strings_accessor" Params "Model" . "Entries" .Strings "Type" "string" }} - {{ template "ts_numbers_accessor" Params "Model" . "Entries" .Int32s "Type" "int32" }} - {{ template "ts_numbers_accessor" Params "Model" . "Entries" .Int64s "Type" "int64" }} - {{ template "ts_numbers_accessor" Params "Model" . "Entries" .Uint32s "Type" "uint32" }} - {{ template "ts_numbers_accessor" Params "Model" . "Entries" .Uint64s "Type" "uint64" }} - {{ template "ts_numbers_accessor" Params "Model" . "Entries" .Float32s "Type" "float32" }} - {{ template "ts_numbers_accessor" Params "Model" . "Entries" .Float64s "Type" "float32" }} - - {{ template "ts_models_accessor" . }} - {{ template "ts_modelarrays_accessor" . }} - {{ template "ts_enums_accessor" . }} - - /** - * @throws {Error} - */ - encode (encoder: Encoder) { - {{ template "ts_models_encode" . }} - {{ template "ts_modelarrays_encode" . }} - - {{ template "ts_primitives_encode" Params "Entries" .Strings "Type" "string" }} - {{ template "ts_arrays_encode" Params "Entries" .StringArrays "Type" "string" }} - {{ template "ts_maps_encode" Params "Entries" .StringMaps "Type" "string" }} - - {{ template "ts_primitives_encode" Params "Entries" .Int32s "Type" "int32" }} - {{ template "ts_arrays_encode" Params "Entries" .Int32Arrays "Type" "int32" }} - {{ template "ts_maps_encode" Params "Entries" .Int32Maps "Type" "int32" }} - - {{ template "ts_primitives_encode" Params "Entries" .Int64s "Type" "int64" }} - {{ template "ts_arrays_encode" Params "Entries" .Int64Arrays "Type" "int64" }} - {{ template "ts_maps_encode" Params "Entries" .Int64Maps "Type" "int64" }} - - {{ template "ts_primitives_encode" Params "Entries" .Uint32s "Type" "uint32" }} - {{ template "ts_arrays_encode" Params "Entries" .Uint32Arrays "Type" "uint32" }} - {{ template "ts_maps_encode" Params "Entries" .Uint32Maps "Type" "uint32" }} - - {{ template "ts_primitives_encode" Params "Entries" .Uint64s "Type" "uint64" }} - {{ template "ts_arrays_encode" Params "Entries" .Uint64Arrays "Type" "uint64" }} - {{ template "ts_maps_encode" Params "Entries" .Uint64Maps "Type" "uint64" }} - - {{ template "ts_primitives_encode" Params "Entries" .Float32s "Type" "float32" }} - {{ template "ts_arrays_encode" Params "Entries" .Float32Arrays "Type" "float32" }} - - {{ template "ts_primitives_encode" Params "Entries" .Float64s "Type" "float64" }} - {{ template "ts_arrays_encode" Params "Entries" .Float64Arrays "Type" "float64" }} - - {{ template "ts_primitives_encode" Params "Entries" .Enums "Type" "uint32" }} - {{ template "ts_arrays_encode" Params "Entries" .EnumArrays "Type" "uint32" }} - {{ template "ts_maps_encode" Params "Entries" .EnumMaps "Type" "uint32" }} - - {{ template "ts_primitives_encode" Params "Entries" .Bytes "Type" "bytes" }} - {{ template "ts_arrays_encode" Params "Entries" .BytesArrays "Type" "bytes" }} - - {{ template "ts_primitives_encode" Params "Entries" .Bools "Type" "bool" }} - {{ template "ts_arrays_encode" Params "Entries" .BoolArrays "Type" "bool" }} - } - - /** - * @throws {Error} - */ - static decode (decoder: Decoder): {{ .Name }} | undefined { - if (decoder.null()) { - return undefined - } - - return new {{ .Name }}(decoder); - } - - /** - * @throws {Error} - */ - static encode_undefined (encoder: Encoder) { - encoder.null(); - } - } - -{{ end -}} \ No newline at end of file diff --git a/extension/generator/templates/validators.rs.templ b/extension/generator/templates/validators.rs.templ deleted file mode 100644 index 5308a27d..00000000 --- a/extension/generator/templates/validators.rs.templ +++ /dev/null @@ -1,53 +0,0 @@ -{{ define "rs_numbers_limit_validator" }} -{{- if . }} - {{- if and .Maximum .Minimum }} - if v > {{ .Maximum }} || v < {{ .Minimum }} { - return Err(Box::::from("value must be between { .Minimum }} and {{ .Maximum }}")); - } - {{- else if .Minimum }} - if v < {{ .Minimum }} { - return Err(Box::::from("value must be greater than or equal to {{ .Minimum }}")); - } - {{- else if .Maximum }} - if v > {{ .Maximum }} { - return Err(Box::::from("value must be less than or equal to {{ .Maximum }}")); - } - {{- end }} -{{- end }} -{{ end }} - -{{ define "rs_regex_validator" }} - {{- if . }} - if !Regex::new("^[a-zA-Z0-9]*$")?.is_match(v.as_str()) { - return Err(Box::::from("value must match {{ .Expression }}")); - } - {{- end }} -{{ end }} - -{{ define "rs_length_validator" }} - {{- if . }} - {{- if and .Maximum .Minimum }} - if v.len() > {{ .Maximum }} || v.len() < {{ .Minimum }} { - return Err(Box::::from("value must be between { .Minimum }} and {{ .Maximum }}")); - } - {{- else if .Minimum }} - if v.len() < {{ .Minimum }} { - return Err(Box::::from("value must be greater than or equal to {{ .Minimum }}")); - } - {{- else if .Maximum }} - if v.len() > {{ .Maximum }} { - return Err(Box::::from("value must be less than or equal to {{ .Maximum }}")); - } - {{- end }} - {{- end }} -{{ end }} - -{{ define "rs_case_modifier" }} - {{- if . }} - {{- if eq .Kind "upper" }} - v = v.to_uppercase(); - {{- else if eq .Kind "lower" }} - v = v.to_lowercase(); - {{- end }} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/generator/templates/validators.ts.templ b/extension/generator/templates/validators.ts.templ deleted file mode 100644 index 0d25c690..00000000 --- a/extension/generator/templates/validators.ts.templ +++ /dev/null @@ -1,53 +0,0 @@ -{{ define "ts_numbers_limit_validator" }} -{{- if . }} - {{- if and .Maximum .Minimum }} - if (val > {{ .Maximum }} || val < {{ .Minimum }}) { - throw new Error("value must be between {{ .Minimum }} and {{ .Maximum }}"); - } - {{- else if .Minimum }} - if (val < {{ .Minimum }}) { - throw new Error("value must be greater or equal to {{ .Minimum }}"); - } - {{- else if .Maximum }} - if (val > {{ .Maximum }}) { - throw new Error("value must be less than or equal to {{ .Maximum }}"); - } - {{- end }} -{{- end }} -{{ end }} - -{{ define "ts_regex_validator" }} - {{- if . }} - if (/{{ .Expression }}/.test(val) === false) { - throw new Error("value must match {{ .Expression }}"); - } - {{- end }} -{{ end }} - -{{ define "ts_length_validator" }} - {{- if . }} - {{- if and .Maximum .Minimum }} - if (val.length > {{ .Maximum }} || val.length < {{ .Minimum }}) { - throw new Error("length must be between {{ .Minimum }} and {{ .Maximum }}"); - } - {{- else if .Minimum }} - if (val.length < {{ .Minimum }}) { - throw new Error("length must be greater than or equal to {{ .Minimum }}"); - } - {{- else if .Maximum }} - if (val.length > {{ .Maximum }}) { - throw new Error("length must be less than or equal to {{ .Maximum }}"); - } - {{- end }} - {{- end }} -{{ end }} - -{{ define "ts_case_modifier" }} - {{- if . }} - {{- if eq .Kind "upper" }} - val = val.toUpperCase(); - {{- else if eq .Kind "lower" }} - val = val.toLowerCase(); - {{- end }} - {{- end }} -{{ end }} \ No newline at end of file diff --git a/extension/schema.go b/extension/schema.go index 7b81bcad..7216e872 100644 --- a/extension/schema.go +++ b/extension/schema.go @@ -17,6 +17,7 @@ package extension import ( + "crypto/sha256" "errors" "fmt" "os" @@ -335,6 +336,200 @@ func (s *Schema) Validate() error { } +// Hash returns the SHA256 hash of the schema +func (s *Schema) Hash() ([]byte, error) { + d, err := s.Encode() + if err != nil { + return nil, err + } + + h := sha256.New() + if _, err = h.Write(d); err != nil { + return nil, err + } + return h.Sum(nil), nil +} + +// Clone returns a deep copy of the schema +func (s *Schema) Clone() (*Schema, error) { + clone := new(Schema) + encoded, err := s.Encode() + if err != nil { + return nil, err + } + if err = clone.Decode(encoded); err != nil { + return nil, err + } + return clone, nil +} + +// CloneWithDisabledAccessorsValidatorsAndModifiers returns a clone of the +// schema with all accessors, validators, and modifiers disabled +func (s *Schema) CloneWithDisabledAccessorsValidatorsAndModifiers() (*Schema, error) { + clone, err := s.Clone() + if err != nil { + return nil, err + } + clone.hasCaseModifier = false + clone.hasLimitValidator = false + clone.hasRegexValidator = false + clone.hasLengthValidator = false + for _, model := range clone.Models { + for _, modelReference := range model.Models { + modelReference.Accessor = false + } + + for _, modelReferenceArray := range model.ModelArrays { + modelReferenceArray.Accessor = + false + } + + for _, str := range model.Strings { + var accessorValue bool + str.Accessor = &accessorValue + str.CaseModifier = nil + str.LengthValidator = nil + str.RegexValidator = nil + } + + for _, strArray := range model.StringArrays { + var accessorValue bool + strArray.Accessor = &accessorValue + } + + for _, strMap := range model.StringMaps { + var accessorValue bool + strMap.Accessor = &accessorValue + } + + for _, i32 := range model.Int32s { + var accessorValue bool + i32.Accessor = &accessorValue + i32.LimitValidator = nil + } + + for _, i32Array := range model.Int32Arrays { + var accessorValue bool + i32Array.Accessor = &accessorValue + } + + for _, i32Map := range model.Int32Maps { + var accessorValue bool + i32Map.Accessor = &accessorValue + } + + for _, i64 := range model.Int64s { + var accessorValue bool + i64.Accessor = &accessorValue + i64.LimitValidator = nil + } + + for _, i64Array := range model.Int64Arrays { + var accessorValue bool + i64Array.Accessor = &accessorValue + } + + for _, i64Map := range model.Int64Maps { + var accessorValue bool + i64Map.Accessor = &accessorValue + } + + for _, u32 := range model.Uint32s { + var accessorValue bool + u32.Accessor = &accessorValue + u32.LimitValidator = nil + } + + for _, u32Array := range model.Uint32Arrays { + var accessorValue bool + u32Array.Accessor = &accessorValue + } + + for _, u32Map := range model.Uint32Maps { + var accessorValue bool + u32Map.Accessor = &accessorValue + } + + for _, u64 := range model.Uint64s { + var accessorValue bool + u64.Accessor = &accessorValue + u64.LimitValidator = nil + } + + for _, u64Array := range model.Uint64Arrays { + var accessorValue bool + u64Array.Accessor = &accessorValue + } + + for _, u64Map := range model.Uint64Maps { + var accessorValue bool + u64Map.Accessor = &accessorValue + } + + for _, f32 := range model.Float32s { + var accessorValue bool + f32.Accessor = &accessorValue + f32.LimitValidator = nil + } + + for _, f32Array := range model.Float32Arrays { + var accessorValue bool + f32Array.Accessor = &accessorValue + } + + for _, f64 := range model.Float64s { + var accessorValue bool + f64.Accessor = &accessorValue + f64.LimitValidator = nil + } + + for _, f64Array := range model.Float64Arrays { + var accessorValue bool + f64Array.Accessor = &accessorValue + } + + for _, boolean := range model.Bools { + boolean.Accessor = false + } + + for _, booleanArray := range model.BoolArrays { + booleanArray.Accessor = false + } + + for _, b := range model.Bytes { + b.Accessor = false + } + + for _, bytesArray := range model.BytesArrays { + bytesArray.Accessor = false + } + + for _, enumReference := range model.Enums { + enumReference.Accessor = false + } + + for _, enumReferenceArray := range model.EnumArrays { + enumReferenceArray.Accessor = false + } + + for _, enumReferenceMap := range model.EnumMaps { + enumReferenceMap.Accessor = false + } + } + + return clone, clone.validateAndNormalize() +} + +// validateAndNormalize validates the Schema and normalizes it +// +// Note: This function modifies the Schema in-place +func (s *Schema) validateAndNormalize() error { + + // TODO... + + return nil +} + func (s *Schema) HasLimitValidator() bool { return s.hasLimitValidator } diff --git a/storage/extension.go b/storage/extension.go new file mode 100644 index 00000000..8b6cc22a --- /dev/null +++ b/storage/extension.go @@ -0,0 +1,337 @@ +/* + Copyright 2022 Loophole Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Package storage is used to store and retrieve built Scale Functions +package storage + +import ( + "encoding/hex" + "fmt" + "os" + "path" + "path/filepath" + + "github.com/loopholelabs/scale/extension" + "github.com/loopholelabs/scale/extension/generator" + "github.com/loopholelabs/scale/scalefunc" +) + +const ( + ExtensionDirectory = "extensions" +) + +var ( + DefaultExtension *ExtensionStorage +) + +type Extension struct { + Name string + Tag string + Schema *extension.Schema + Hash string + Organization string +} + +type ExtensionStorage struct { + Directory string +} + +func init() { + homeDir, err := os.UserHomeDir() + if err != nil { + panic(err) + } + DefaultExtension, err = NewExtension(path.Join(homeDir, DefaultDirectory, ExtensionDirectory)) + if err != nil { + panic(err) + } +} + +func NewExtension(baseDirectory string) (*ExtensionStorage, error) { + err := os.MkdirAll(baseDirectory, 0755) + if err != nil { + if !os.IsExist(err) { + return nil, err + } + } + + return &ExtensionStorage{ + Directory: baseDirectory, + }, nil +} + +// Get returns the Scale Extension with the given name, tag, and organization. +// The hash parameter is optional and can be used to check for a specific hash. +func (s *ExtensionStorage) Get(name string, tag string, org string, hash string) (*Extension, error) { + if name == "" || !scalefunc.ValidString(name) { + return nil, ErrInvalidName + } + + if tag == "" || !scalefunc.ValidString(tag) { + return nil, ErrInvalidTag + } + + if org == "" || !scalefunc.ValidString(org) { + return nil, ErrInvalidOrganization + } + + if hash != "" { + f := s.extensionName(name, tag, org, hash) + p := s.fullPath(f) + + stat, err := os.Stat(p) + if err != nil { + return nil, err + } + + if !stat.IsDir() { + return nil, fmt.Errorf("found extension is a file not a directory %s/%s:%s", org, name, tag) + } + + sig, err := extension.ReadSchema(path.Join(p, "extension")) + if err != nil { + return nil, err + } + + return &Extension{ + Name: name, + Tag: tag, + Schema: sig, + Hash: hash, + Organization: org, + }, nil + } + + f := s.extensionSearch(name, tag, org) + p := s.fullPath(f) + + matches, err := filepath.Glob(p) + if err != nil { + return nil, err + } + + if len(matches) == 0 { + return nil, nil + } + + if len(matches) > 1 { + return nil, fmt.Errorf("multiple matches found for %s/%s:%s", org, name, tag) + } + + stat, err := os.Stat(matches[0]) + if err != nil { + return nil, err + } + + if !stat.IsDir() { + return nil, fmt.Errorf("found extension is a file not a directory %s/%s:%s", org, name, tag) + } + + sig, err := extension.ReadSchema(path.Join(matches[0], "extension")) + if err != nil { + return nil, err + } + + return &Extension{ + Name: name, + Tag: tag, + Schema: sig, + Hash: getHashFromName(filepath.Base(matches[0])), + Organization: getOrgFromName(filepath.Base(matches[0])), + }, nil +} + +func (s *ExtensionStorage) Path(name string, tag string, org string, hash string) (string, error) { + if name == "" || !scalefunc.ValidString(name) { + return "", ErrInvalidName + } + + if tag == "" || !scalefunc.ValidString(tag) { + return "", ErrInvalidTag + } + + if org == "" || !scalefunc.ValidString(org) { + return "", ErrInvalidOrganization + } + + if hash != "" { + f := s.extensionName(name, tag, org, hash) + p := s.fullPath(f) + + stat, err := os.Stat(p) + if err != nil { + return "", err + } + + if !stat.IsDir() { + return "", fmt.Errorf("found extension is a file not a directory %s/%s:%s", org, name, tag) + } + + return p, nil + } + + f := s.extensionSearch(name, tag, org) + p := s.fullPath(f) + + matches, err := filepath.Glob(p) + if err != nil { + return "", err + } + + if len(matches) == 0 { + return "", nil + } + + if len(matches) > 1 { + return "", fmt.Errorf("multiple matches found for %s/%s:%s", org, name, tag) + } + + stat, err := os.Stat(matches[0]) + if err != nil { + return "", err + } + + if !stat.IsDir() { + return "", fmt.Errorf("found extension is a file not a directory %s/%s:%s", org, name, tag) + } + + return matches[0], nil +} + +// Put stores the Scale Extension with the given name, tag, organization +func (s *ExtensionStorage) Put(name string, tag string, org string, sig *extension.Schema) error { + hash, err := sig.Hash() + if err != nil { + return err + } + + hashString := hex.EncodeToString(hash) + + f := s.extensionName(name, tag, org, hashString) + directory := s.fullPath(f) + err = os.MkdirAll(directory, 0755) + if err != nil { + return err + } + + err = GenerateExtension(sig, name, tag, org, directory) + if err != nil { + return err + } + + return nil +} + +// Delete removes the Scale Extension with the given name, tag, org, and hash +func (s *ExtensionStorage) Delete(name string, tag string, org string, hash string) error { + return os.RemoveAll(s.fullPath(s.extensionName(name, tag, org, hash))) +} + +// List returns all the Scale Extensions stored in the storage +func (s *ExtensionStorage) List() ([]Extension, error) { + entries, err := os.ReadDir(s.Directory) + if err != nil { + return nil, fmt.Errorf("failed to read storage directory %s: %w", s.Directory, err) + } + var scaleExtensionEntries []Extension + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + sig, err := extension.ReadSchema(path.Join(s.fullPath(entry.Name()), "extension")) + if err != nil { + return nil, fmt.Errorf("failed to decode scale extension %s: %w", s.fullPath(entry.Name()), err) + } + scaleExtensionEntries = append(scaleExtensionEntries, Extension{ + Name: getNameFromName(entry.Name()), + Tag: getTagFromName(entry.Name()), + Schema: sig, + Hash: getHashFromName(entry.Name()), + Organization: getOrgFromName(entry.Name()), + }) + } + return scaleExtensionEntries, nil +} + +func (s *ExtensionStorage) fullPath(p string) string { + return path.Join(s.Directory, p) +} + +func (s *ExtensionStorage) extensionName(name string, tag string, org string, hash string) string { + return fmt.Sprintf("%s_%s_%s_%s_extension", org, name, tag, hash) +} + +func (s *ExtensionStorage) extensionSearch(name string, tag string, org string) string { + return fmt.Sprintf("%s_%s_%s_*_extension", org, name, tag) +} + +// GenerateExtension generates the extension files and writes them to +// the given path. +func GenerateExtension(sig *extension.Schema, name string, tag string, org string, directory string) error { + encoded, err := sig.Encode() + if err != nil { + return err + } + + err = os.WriteFile(path.Join(directory, "extension"), encoded, 0644) + if err != nil { + return err + } + + err = os.MkdirAll(path.Join(directory, "golang", "guest"), 0755) + if err != nil { + return err + } + + err = os.MkdirAll(path.Join(directory, "golang", "host"), 0755) + if err != nil { + return err + } + + guestPackage, err := generator.GenerateGuestLocal(&generator.Options{ + Extension: sig, + GolangPackageImportPath: "extension", + GolangPackageName: "extension", + GolangPackageVersion: "v0.1.0", + }) + if err != nil { + return err + } + + for _, file := range guestPackage.GolangFiles { + err = os.WriteFile(path.Join(directory, "golang", "guest", file.Path()), file.Data(), 0644) + if err != nil { + return err + } + } + + hostPackage, err := generator.GenerateHostLocal(&generator.Options{ + Extension: sig, + }) + if err != nil { + return err + } + + for _, file := range hostPackage.GolangFiles { + err = os.WriteFile(path.Join(directory, "golang", "host", file.Path()), file.Data(), 0644) + if err != nil { + return err + } + } + + return nil +}