From be736e4b56ff470691f9e474d5d63c05c696d68b Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 24 Nov 2025 22:49:00 -0500 Subject: [PATCH 1/6] WIP: Model enums as interfaces. --- internal/generate/responses.go | 2 +- internal/generate/types.go | 220 ++++-- oxide/types.go | 1203 ++++++++++++++++++++++---------- 3 files changed, 986 insertions(+), 439 deletions(-) diff --git a/internal/generate/responses.go b/internal/generate/responses.go index 8507fa1..a749e42 100644 --- a/internal/generate/responses.go +++ b/internal/generate/responses.go @@ -62,7 +62,7 @@ func populateResponseType(name string, r *openapi3.Response) ([]TypeTemplate, [] continue } - tt, et := populateTypeTemplates(respName, s.Value, "") + tt, et := populateTypeTemplates(respName, s.Value, "", "") types = append(types, tt...) enumTypes = append(enumTypes, et...) diff --git a/internal/generate/types.go b/internal/generate/types.go index 3b508b7..bbbadb0 100644 --- a/internal/generate/types.go +++ b/internal/generate/types.go @@ -34,6 +34,25 @@ type TypeTemplate struct { Type string // Fields holds the information for the field Fields []TypeFields + + // DiscriminatorKey is the name of the discriminator key used to determine the type of a complex oneOf field: commonly "type", "kind", etc. + DiscriminatorKey string + // DiscriminatorField + DiscriminatorField string + // DiscriminatorType is the generated type name of the discriminator field, and should be constructed as "{{.OneOfName}}Type": MetricType, ValueArrayType, etc. + DiscriminatorType string + // DiscriminatorMappings maps oneOf enum constant (e.g. DatumTypeBool) to their concrete types (e.g. DatumBool). + DiscriminatorMappings []DiscriminatorMapping + + VariantField string + VariantInterface string +} + +// DiscriminatorMapping maps a discriminator enum value to its concrete type +type DiscriminatorMapping struct { + EnumConstant string // The enum constant to match in switch (e.g., "DatumTypeBool") + ConcreteType string // The concrete type to unmarshal into (e.g., "DatumBool") + ObjectType string } // TypeFields holds the information for each type field @@ -256,7 +275,7 @@ func constructTypes(schemas openapi3.Schemas) ([]TypeTemplate, []EnumTemplate) { // Set name as a valid Go type name name = strcase.ToCamel(name) - typeTpl, enumTpl := populateTypeTemplates(name, s.Value, "") + typeTpl, enumTpl := populateTypeTemplates(name, s.Value, "", "") typeCollection = append(typeCollection, typeTpl...) enumCollection = append(enumCollection, enumTpl...) } @@ -326,7 +345,12 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect fmt.Fprintf(f, "%s\n", splitDocString(tt.Description)) fmt.Fprintf(f, "type %s %s", tt.Name, tt.Type) - if tt.Fields != nil { + + if tt.Type == "interface" { + fmt.Fprintf(f, " {\n") + fmt.Fprintf(f, "\tis%s()\n", tt.Name) + fmt.Fprint(f, "}\n") + } else if tt.Fields != nil { fmt.Fprint(f, " {\n") for _, ft := range tt.Fields { if ft.Description != "" { @@ -336,6 +360,48 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect } fmt.Fprint(f, "}\n") } + + if tt.DiscriminatorKey != "" && tt.VariantField != "" { + fmt.Fprintf(f, "func (v *%s) UnmarshalJSON(data []byte) error {\n", tt.Name) + fmt.Fprintf(f, "\tvar peek struct {\n") + fmt.Fprintf(f, "\t\tDiscriminator %s `json:\"%s\"`\n", tt.DiscriminatorType, tt.DiscriminatorKey) + fmt.Fprintf(f, "\t}\n") + fmt.Fprintf(f, "\tif err := json.Unmarshal(data, &peek); err != nil {\n") + fmt.Fprintf(f, "\t\treturn err\n") + fmt.Fprintf(f, "\t}\n") + fmt.Fprintf(f, "\tswitch peek.Discriminator {\n") + + for _, mapping := range tt.DiscriminatorMappings { + fmt.Fprintf(f, "\tcase %s:\n", mapping.EnumConstant) + + if slices.Contains([]string{"string", "int", "*bool"}, mapping.ObjectType) { + fmt.Fprintf(f, "\t\ttype value struct {\n") + fmt.Fprintf(f, "\t\t\tValue %s `json:\"%s\"`\n", mapping.ConcreteType, strings.ToLower(tt.VariantField)) + fmt.Fprintf(f, "\t\t}\n") + fmt.Fprintf(f, "\t\tvar val value\n") + fmt.Fprintf(f, "\t\tif err := json.Unmarshal(data, &val); err != nil {\n") + fmt.Fprintf(f, "\t\t\treturn err\n") + fmt.Fprintf(f, "\t\t}\n") + fmt.Fprintf(f, "\tv.%s = val.Value\n", tt.VariantField) + } else { + fmt.Fprintf(f, "\t\tvar val %s\n", mapping.ConcreteType) + fmt.Fprintf(f, "\t\tif err := json.Unmarshal(data, &val); err != nil {\n") + fmt.Fprintf(f, "\t\t\treturn err\n") + fmt.Fprintf(f, "\t\t}\n") + fmt.Fprintf(f, "\tv.%s = val\n", tt.VariantField) + } + } + fmt.Fprintf(f, "\tdefault:\n") + fmt.Fprintf(f, "\t\treturn fmt.Errorf(\"unknown %s discriminator value for %s %%s: %%v\", string(data), peek.Discriminator)\n", tt.Name, tt.DiscriminatorKey) + fmt.Fprintf(f, "\t}\n") + fmt.Fprintf(f, "\tv.%s = peek.Discriminator\n", tt.DiscriminatorField) + fmt.Fprintf(f, "\treturn nil\n") + fmt.Fprint(f, "}\n") + } + if tt.VariantInterface != "" { + fmt.Fprintf(f, "\n") + fmt.Fprintf(f, "func (%s) is%s() {}\n", tt.Name, tt.VariantInterface) + } fmt.Fprint(f, "\n") } @@ -381,7 +447,7 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect // populateTypeTemplates populates the template of a type definition for the given schema. // The additional parameter is only used as a suffix for the type name. // This is mostly for oneOf types. -func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string) ([]TypeTemplate, []EnumTemplate) { +func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string, variantInterface string) ([]TypeTemplate, []EnumTemplate) { typeName := name // Type name will change for each enum type @@ -402,6 +468,8 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string s.Type = &openapi3.Types{"string"} } + typeTpl.VariantInterface = variantInterface + switch ot := getObjectType(s); ot { case "string_enum": enums, tt, et := createStringEnum(s, collectEnumStringTypes, name, typeName) @@ -419,20 +487,21 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string typeTpl.Name = typeName case "object": typeTpl = createTypeObject(s, name, typeName, formatTypeDescription(typeName, s)) + typeTpl.VariantInterface = variantInterface // Iterate over the properties and append the types, if we need to. properties := sortedKeys(s.Properties) for _, k := range properties { v := s.Properties[k] if isLocalEnum(v) { - tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "") + tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "", "") types = append(types, tt...) enumTypes = append(enumTypes, et...) } // TODO: So far this code is never hit with the current openapi spec if isLocalObject(v) { - tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "") + tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "", "") types = append(types, tt...) enumTypes = append(enumTypes, et...) } @@ -624,6 +693,10 @@ func createStringEnum(s *openapi3.Schema, stringEnums map[string][]string, name, // Probably not the best approach, but will leave them this way until I come up with // a more idiomatic solution. Keep an eye out on this one to refine. func createAllOf(s *openapi3.Schema, stringEnums map[string][]string, name, typeName string) []TypeTemplate { + + // if typeName == "VpcFirewallRuleTarget" { + // panic("sad") + // } typeTpls := make([]TypeTemplate, 0) // Make sure we don't redeclare the enum type. @@ -650,54 +723,48 @@ func createAllOf(s *openapi3.Schema, stringEnums map[string][]string, name, type func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []EnumTemplate) { var parsedProperties []string - var properties []string - var genericTypes []string enumTpls := make([]EnumTemplate, 0) typeTpls := make([]TypeTemplate, 0) fields := make([]TypeFields, 0) - for _, v := range s.OneOf { - // Iterate over all the schema components in the spec and write the types. - keys := sortedKeys(v.Value.Properties) - for _, prop := range keys { - p := v.Value.Properties[prop] - // We want to collect all the unique properties to create our global oneOf type. - propertyType := convertToValidGoType(prop, typeName, p) - properties = append(properties, prop+"="+propertyType) + discriminator := "" + propertyToVariants := map[string]map[string]struct{}{} + propertyToObjectTypes := map[string]string{} + for _, v := range s.OneOf { + for propName, prop := range v.Value.Properties { + if len(prop.Value.Enum) == 1 { + discriminator = propName + } + if _, ok := propertyToVariants[propName]; !ok { + propertyToVariants[propName] = map[string]struct{}{} + } + goType := convertToValidGoType(propName, typeName, prop) + propertyToVariants[propName][goType] = struct{}{} + propertyToObjectTypes[propName] = getObjectType(prop.Value) } } - - // When dealing with oneOf sometimes property types will not be the same, we want to - // catch these to set them as "any" when we generate the type. - typeKeys := []string{} - // First we gather all unique properties - for _, v := range properties { - parts := strings.Split(v, "=") - key := parts[0] - if !slices.Contains(typeKeys, key) { - typeKeys = append(typeKeys, key) + variantField := "" + variantFields := []string{} + variantTypes := []string{} + for propName, variants := range propertyToVariants { + if len(variants) > 1 { + variantFields = append(variantFields, propName) + variantTypes = append(variantTypes, propName) } } - - // For each of the properties above we gather all possible types - // and gather all of those that are not. We will be setting those - // as a generic type - for _, k := range typeKeys { - values := []string{} - for _, v := range properties { - parts := strings.Split(v, "=") - key := parts[0] - value := parts[1] - if key == k { - values = append(values, value) - } - } - - if !allItemsAreSame(values) { - genericTypes = append(genericTypes, k) - } + variantInterface := "" + if len(variantFields) == 1 && len(variantTypes) == 1 { + variantField = strcase.ToCamel(variantFields[0]) + variantInterface = fmt.Sprintf("%s%s", typeName, strcase.ToCamel(variantTypes[0])) + typeTpls = append(typeTpls, TypeTemplate{ + Name: variantInterface, + Type: "interface", + }) } + discriminatorMappings := []DiscriminatorMapping{} + discriminatorToDiscriminatorType := map[string]string{} + for _, v := range s.OneOf { // We want to iterate over the properties of the embedded object // and find the type that is a string. @@ -707,16 +774,33 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E keys := sortedKeys(v.Value.Properties) for _, prop := range keys { p := v.Value.Properties[prop] + propertyName := strcase.ToCamel(prop) // We want to collect all the unique properties to create our global oneOf type. propertyType := convertToValidGoType(prop, typeName, p) + if propertyType == "string" && len(p.Value.Enum) == 1 { + discriminatorToDiscriminatorType[prop] = typeName + strcase.ToCamel(prop) + discriminatorMappings = append(discriminatorMappings, DiscriminatorMapping{ + EnumConstant: fmt.Sprintf("%s%s%s", typeName, propertyName, strcase.ToCamel(p.Value.Enum[0].(string))), + ConcreteType: fmt.Sprintf("%s%s", typeName, strcase.ToCamel(p.Value.Enum[0].(string))), + // ObjectType: propertyToObjectTypes[variantTypes[0]], + }) + if len(variantFields) > 0 { + vp := v.Value.Properties[strings.ToLower(variantField)] + if vp != nil { + discriminatorMappings[len(discriminatorMappings)-1].ObjectType = propertyToObjectTypes[variantFields[0]] + + } + } + } + // Check if we have an enum in order to use the corresponding type instead of // "string" if propertyType == "string" && len(p.Value.Enum) != 0 { propertyType = typeName + strcase.ToCamel(prop) } - propertyName := strcase.ToCamel(prop) + propertyName = strcase.ToCamel(prop) // Avoids duplication for every enum if !containsMatchFirstWord(parsedProperties, propertyName) { @@ -728,8 +812,8 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E } // We set the type of a field as "any" if every element of the oneOf property isn't the same - if slices.Contains(genericTypes, prop) { - field.Type = "any" + if slices.Contains(variantTypes, prop) { + field.Type = variantInterface } // Check if the field is nullable and use omitzero instead of omitempty. @@ -765,9 +849,34 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E // TODO: This is the only place that has an "additional name" at the end // TODO: This is where the "allOf" is being detected - tt, et := populateTypeTemplates(name, v.Value, enumFieldName) - typeTpls = append(typeTpls, tt...) - enumTpls = append(enumTpls, et...) + if len(variantFields) == 1 && v.Value.Properties[variantFields[0]] != nil { + variantType := getObjectType(v.Value.Properties[variantFields[0]].Value) + // if slices.Contains([]string{"string", "*bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", + // "uint16", "uint32", "uint64", "uintptr", "float32", "float64", "bytes"}, variantType) { + if !slices.Contains([]string{"array", "object", "all_of", "any_of", "one_of", "string_enum"}, variantType) { + tt, _ := populateTypeTemplates(name, v.Value.Properties[variantFields[0]].Value, enumFieldName, variantInterface) + typeTpls = append(typeTpls, tt...) + // enumTpls = append(enumTpls, et...) + fooTT, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) + // typeTpls = append(typeTpls, tt...) + enumTpls = append(enumTpls, et...) + + for idx, tt := range fooTT { + if strings.HasSuffix(tt.Name, "Type") { + fmt.Printf("DEBUG TT TYPE %d %s %s %+v\n", idx, name, enumFieldName, tt) + typeTpls = append(typeTpls, tt) + } + } + } else { + tt, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) + typeTpls = append(typeTpls, tt...) + enumTpls = append(enumTpls, et...) + } + } else { + tt, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) + typeTpls = append(typeTpls, tt...) + enumTpls = append(enumTpls, et...) + } } // TODO: For now AllOf values within a OneOf are treated as enums @@ -782,10 +891,15 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E // Make sure to only create structs if the oneOf is not a replacement for enums on the API spec if len(fields) > 0 { typeTpl := TypeTemplate{ - Description: formatTypeDescription(typeName, s), - Name: typeName, - Type: "struct", - Fields: fields, + Description: formatTypeDescription(typeName, s), + Name: typeName, + Type: "struct", + Fields: fields, + DiscriminatorKey: discriminator, + DiscriminatorField: strcase.ToCamel(discriminator), + DiscriminatorType: discriminatorToDiscriminatorType[discriminator], + DiscriminatorMappings: discriminatorMappings, + VariantField: variantField, } typeTpls = append(typeTpls, typeTpl) } diff --git a/oxide/types.go b/oxide/types.go index 4bc1a62..4775e94 100644 --- a/oxide/types.go +++ b/oxide/types.go @@ -7,6 +7,7 @@ package oxide import ( + "encoding/json" "fmt" "io" "time" @@ -1923,128 +1924,72 @@ type CurrentUser struct { SiloName Name `json:"silo_name" yaml:"silo_name"` } -// DatumType is the type definition for a DatumType. -type DatumType string +type DatumDatum interface { + isDatumDatum() +} // DatumBool is the type definition for a DatumBool. -// -// Required fields: -// - Datum -// - Type -type DatumBool struct { - Datum *bool `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumBool *bool + +func (DatumBool) isDatumDatum() {} + +// DatumType is the type definition for a DatumType. +type DatumType string // DatumI8 is the type definition for a DatumI8. -// -// Required fields: -// - Datum -// - Type -type DatumI8 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI8 int8 + +func (DatumI8) isDatumDatum() {} // DatumU8 is the type definition for a DatumU8. -// -// Required fields: -// - Datum -// - Type -type DatumU8 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU8 uint8 + +func (DatumU8) isDatumDatum() {} // DatumI16 is the type definition for a DatumI16. -// -// Required fields: -// - Datum -// - Type -type DatumI16 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI16 int16 + +func (DatumI16) isDatumDatum() {} // DatumU16 is the type definition for a DatumU16. -// -// Required fields: -// - Datum -// - Type -type DatumU16 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU16 uint16 + +func (DatumU16) isDatumDatum() {} // DatumI32 is the type definition for a DatumI32. -// -// Required fields: -// - Datum -// - Type -type DatumI32 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI32 int32 + +func (DatumI32) isDatumDatum() {} // DatumU32 is the type definition for a DatumU32. -// -// Required fields: -// - Datum -// - Type -type DatumU32 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU32 uint32 + +func (DatumU32) isDatumDatum() {} // DatumI64 is the type definition for a DatumI64. -// -// Required fields: -// - Datum -// - Type -type DatumI64 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI64 int64 + +func (DatumI64) isDatumDatum() {} // DatumU64 is the type definition for a DatumU64. -// -// Required fields: -// - Datum -// - Type -type DatumU64 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU64 uint64 + +func (DatumU64) isDatumDatum() {} // DatumF32 is the type definition for a DatumF32. -// -// Required fields: -// - Datum -// - Type -type DatumF32 struct { - Datum float64 `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumF32 float64 + +func (DatumF32) isDatumDatum() {} // DatumF64 is the type definition for a DatumF64. -// -// Required fields: -// - Datum -// - Type -type DatumF64 struct { - Datum float64 `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumF64 float64 + +func (DatumF64) isDatumDatum() {} // DatumString is the type definition for a DatumString. -// -// Required fields: -// - Datum -// - Type -type DatumString struct { - Datum string `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumString string + +func (DatumString) isDatumDatum() {} // DatumBytes is the type definition for a DatumBytes. // @@ -2056,6 +2001,8 @@ type DatumBytes struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumBytes) isDatumDatum() {} + // DatumCumulativeI64 is the type definition for a DatumCumulativeI64. // // Required fields: @@ -2067,6 +2014,8 @@ type DatumCumulativeI64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeI64) isDatumDatum() {} + // DatumCumulativeU64 is the type definition for a DatumCumulativeU64. // // Required fields: @@ -2078,6 +2027,8 @@ type DatumCumulativeU64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeU64) isDatumDatum() {} + // DatumCumulativeF32 is the type definition for a DatumCumulativeF32. // // Required fields: @@ -2089,6 +2040,8 @@ type DatumCumulativeF32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeF32) isDatumDatum() {} + // DatumCumulativeF64 is the type definition for a DatumCumulativeF64. // // Required fields: @@ -2100,6 +2053,8 @@ type DatumCumulativeF64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeF64) isDatumDatum() {} + // DatumHistogramI8 is the type definition for a DatumHistogramI8. // // Required fields: @@ -2117,6 +2072,8 @@ type DatumHistogramI8 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI8) isDatumDatum() {} + // DatumHistogramU8 is the type definition for a DatumHistogramU8. // // Required fields: @@ -2134,6 +2091,8 @@ type DatumHistogramU8 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU8) isDatumDatum() {} + // DatumHistogramI16 is the type definition for a DatumHistogramI16. // // Required fields: @@ -2151,6 +2110,8 @@ type DatumHistogramI16 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI16) isDatumDatum() {} + // DatumHistogramU16 is the type definition for a DatumHistogramU16. // // Required fields: @@ -2168,6 +2129,8 @@ type DatumHistogramU16 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU16) isDatumDatum() {} + // DatumHistogramI32 is the type definition for a DatumHistogramI32. // // Required fields: @@ -2185,6 +2148,8 @@ type DatumHistogramI32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI32) isDatumDatum() {} + // DatumHistogramU32 is the type definition for a DatumHistogramU32. // // Required fields: @@ -2202,6 +2167,8 @@ type DatumHistogramU32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU32) isDatumDatum() {} + // DatumHistogramI64 is the type definition for a DatumHistogramI64. // // Required fields: @@ -2219,6 +2186,8 @@ type DatumHistogramI64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI64) isDatumDatum() {} + // DatumHistogramU64 is the type definition for a DatumHistogramU64. // // Required fields: @@ -2236,6 +2205,8 @@ type DatumHistogramU64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU64) isDatumDatum() {} + // DatumHistogramF32 is the type definition for a DatumHistogramF32. // // Required fields: @@ -2253,6 +2224,8 @@ type DatumHistogramF32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramF32) isDatumDatum() {} + // DatumHistogramF64 is the type definition for a DatumHistogramF64. // // Required fields: @@ -2270,6 +2243,8 @@ type DatumHistogramF64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramF64) isDatumDatum() {} + // DatumMissing is the type definition for a DatumMissing. // // Required fields: @@ -2280,14 +2255,199 @@ type DatumMissing struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumMissing) isDatumDatum() {} + // Datum is a `Datum` is a single sampled data point from a metric. type Datum struct { // Datum is the type definition for a Datum. - Datum any `json:"datum,omitempty" yaml:"datum,omitempty"` + Datum DatumDatum `json:"datum,omitempty" yaml:"datum,omitempty"` // Type is the type definition for a Type. Type DatumType `json:"type,omitempty" yaml:"type,omitempty"` } +func (v *Datum) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator DatumType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case DatumTypeBool: + var val DatumBool + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI8: + var val DatumI8 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU8: + var val DatumU8 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI16: + var val DatumI16 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU16: + var val DatumU16 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI32: + var val DatumI32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU32: + var val DatumU32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI64: + var val DatumI64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU64: + var val DatumU64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeF32: + var val DatumF32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeF64: + var val DatumF64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeString: + var val DatumString + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeBytes: + var val DatumBytes + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeI64: + var val DatumCumulativeI64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeU64: + var val DatumCumulativeU64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeF32: + var val DatumCumulativeF32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeF64: + var val DatumCumulativeF64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI8: + var val DatumHistogramI8 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU8: + var val DatumHistogramU8 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI16: + var val DatumHistogramI16 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU16: + var val DatumHistogramU16 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI32: + var val DatumHistogramI32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU32: + var val DatumHistogramU32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI64: + var val DatumHistogramI64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU64: + var val DatumHistogramU64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramF32: + var val DatumHistogramF32 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramF64: + var val DatumHistogramF64 + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeMissing: + var val DatumMissing + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Datum = val + default: + return fmt.Errorf("unknown Datum discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil +} + // DerEncodedKeyPair is the type definition for a DerEncodedKeyPair. // // Required fields: @@ -2860,135 +3020,202 @@ type FieldSource string // FieldType is the `FieldType` identifies the data type of a target or metric field. type FieldType string -// FieldValueType is the type definition for a FieldValueType. -type FieldValueType string +type FieldValueValue interface { + isFieldValueValue() +} // FieldValueString is the type definition for a FieldValueString. -// -// Required fields: -// - Type -// - Value -type FieldValueString struct { - Type FieldValueType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +type FieldValueString string + +func (FieldValueString) isFieldValueValue() {} + +// FieldValueType is the type definition for a FieldValueType. +type FieldValueType string // FieldValueI8 is the type definition for a FieldValueI8. -// -// Required fields: -// - Type -// - Value -type FieldValueI8 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI8 int8 + +func (FieldValueI8) isFieldValueValue() {} // FieldValueU8 is the type definition for a FieldValueU8. -// -// Required fields: -// - Type -// - Value -type FieldValueU8 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU8 uint8 + +func (FieldValueU8) isFieldValueValue() {} // FieldValueI16 is the type definition for a FieldValueI16. -// -// Required fields: -// - Type -// - Value -type FieldValueI16 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI16 int16 + +func (FieldValueI16) isFieldValueValue() {} // FieldValueU16 is the type definition for a FieldValueU16. -// -// Required fields: -// - Type -// - Value -type FieldValueU16 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU16 uint16 + +func (FieldValueU16) isFieldValueValue() {} // FieldValueI32 is the type definition for a FieldValueI32. -// -// Required fields: -// - Type -// - Value -type FieldValueI32 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI32 int32 + +func (FieldValueI32) isFieldValueValue() {} // FieldValueU32 is the type definition for a FieldValueU32. -// -// Required fields: -// - Type -// - Value -type FieldValueU32 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU32 uint32 + +func (FieldValueU32) isFieldValueValue() {} // FieldValueI64 is the type definition for a FieldValueI64. -// -// Required fields: -// - Type -// - Value -type FieldValueI64 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI64 int64 + +func (FieldValueI64) isFieldValueValue() {} // FieldValueU64 is the type definition for a FieldValueU64. -// -// Required fields: -// - Type -// - Value -type FieldValueU64 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU64 uint64 + +func (FieldValueU64) isFieldValueValue() {} // FieldValueIpAddr is the type definition for a FieldValueIpAddr. -// -// Required fields: -// - Type -// - Value -type FieldValueIpAddr struct { - Type FieldValueType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +type FieldValueIpAddr string + +func (FieldValueIpAddr) isFieldValueValue() {} // FieldValueUuid is the type definition for a FieldValueUuid. -// -// Required fields: -// - Type -// - Value -type FieldValueUuid struct { - Type FieldValueType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +type FieldValueUuid string + +func (FieldValueUuid) isFieldValueValue() {} // FieldValueBool is the type definition for a FieldValueBool. -// -// Required fields: -// - Type -// - Value -type FieldValueBool struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *bool `json:"value" yaml:"value"` -} +type FieldValueBool *bool + +func (FieldValueBool) isFieldValueValue() {} // FieldValue is the `FieldValue` contains the value of a target or metric field. type FieldValue struct { // Type is the type definition for a Type. Type FieldValueType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value FieldValueValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *FieldValue) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator FieldValueType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case FieldValueTypeString: + type value struct { + Value FieldValueString `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeI8: + type value struct { + Value FieldValueI8 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeU8: + type value struct { + Value FieldValueU8 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeI16: + type value struct { + Value FieldValueI16 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeU16: + type value struct { + Value FieldValueU16 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeI32: + type value struct { + Value FieldValueI32 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeU32: + type value struct { + Value FieldValueU32 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeI64: + type value struct { + Value FieldValueI64 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeU64: + type value struct { + Value FieldValueU64 `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeIpAddr: + type value struct { + Value FieldValueIpAddr `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeUuid: + type value struct { + Value FieldValueUuid `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case FieldValueTypeBool: + type value struct { + Value FieldValueBool `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + default: + return fmt.Errorf("unknown FieldValue discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // FinalizeDisk is parameters for finalizing a disk @@ -5343,19 +5570,18 @@ type RouteConfig struct { Routes []Route `json:"routes" yaml:"routes"` } +type RouteDestinationValue interface { + isRouteDestinationValue() +} + +// RouteDestinationIp is the type definition for a RouteDestinationIp. +type RouteDestinationIp string + +func (RouteDestinationIp) isRouteDestinationValue() {} + // RouteDestinationType is the type definition for a RouteDestinationType. type RouteDestinationType string -// RouteDestinationIp is route applies to traffic destined for the specified IP address -// -// Required fields: -// - Type -// - Value -type RouteDestinationIp struct { - Type RouteDestinationType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} - // RouteDestinationIpNet is route applies to traffic destined for the specified IP subnet // // Required fields: @@ -5366,31 +5592,21 @@ type RouteDestinationIpNet struct { Value IpNet `json:"value" yaml:"value"` } -// RouteDestinationVpc is route applies to traffic destined for the specified VPC -// -// Required fields: -// - Type -// - Value -type RouteDestinationVpc struct { - Type RouteDestinationType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (RouteDestinationIpNet) isRouteDestinationValue() {} -// RouteDestinationSubnet is route applies to traffic destined for the specified VPC subnet -// -// Required fields: -// - Type -// - Value -type RouteDestinationSubnet struct { - Type RouteDestinationType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// RouteDestinationVpc is names must begin with a lower case ASCII letter, be composed exclusively of lowercase +// ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may +// contain a UUID. They can be at most 63 characters long. +type RouteDestinationVpc string + +func (RouteDestinationVpc) isRouteDestinationValue() {} + +// RouteDestinationSubnet is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type RouteDestinationSubnet string + +func (RouteDestinationSubnet) isRouteDestinationValue() {} // RouteDestination is a `RouteDestination` is used to match traffic with a routing rule based on the destination // of that traffic. @@ -5401,73 +5617,99 @@ type RouteDestination struct { // Type is the type definition for a Type. Type RouteDestinationType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value any `json:"value,omitempty" yaml:"value,omitempty"` -} + Value RouteDestinationValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *RouteDestination) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator RouteDestinationType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case RouteDestinationTypeIp: + type value struct { + Value RouteDestinationIp `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteDestinationTypeIpNet: + type value struct { + Value RouteDestinationIpNet `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteDestinationTypeVpc: + type value struct { + Value RouteDestinationVpc `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteDestinationTypeSubnet: + type value struct { + Value RouteDestinationSubnet `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + default: + return fmt.Errorf("unknown RouteDestination discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil +} + +type RouteTargetValue interface { + isRouteTargetValue() +} + +// RouteTargetIp is the type definition for a RouteTargetIp. +type RouteTargetIp string + +func (RouteTargetIp) isRouteTargetValue() {} // RouteTargetType is the type definition for a RouteTargetType. type RouteTargetType string -// RouteTargetIp is forward traffic to a particular IP address. -// -// Required fields: -// - Type -// - Value -type RouteTargetIp struct { - Type RouteTargetType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +// RouteTargetVpc is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, +// uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a +// UUID. They can be at most 63 characters long. +type RouteTargetVpc string -// RouteTargetVpc is forward traffic to a VPC -// -// Required fields: -// - Type -// - Value -type RouteTargetVpc struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (RouteTargetVpc) isRouteTargetValue() {} -// RouteTargetSubnet is forward traffic to a VPC Subnet -// -// Required fields: -// - Type -// - Value -type RouteTargetSubnet struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// RouteTargetSubnet is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, +// uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a +// UUID. They can be at most 63 characters long. +type RouteTargetSubnet string -// RouteTargetInstance is forward traffic to a specific instance -// -// Required fields: -// - Type -// - Value -type RouteTargetInstance struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (RouteTargetSubnet) isRouteTargetValue() {} -// RouteTargetInternetGateway is forward traffic to an internet gateway -// -// Required fields: -// - Type -// - Value -type RouteTargetInternetGateway struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// RouteTargetInstance is names must begin with a lower case ASCII letter, be composed exclusively of lowercase +// ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may +// contain a UUID. They can be at most 63 characters long. +type RouteTargetInstance string + +func (RouteTargetInstance) isRouteTargetValue() {} + +// RouteTargetInternetGateway is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type RouteTargetInternetGateway string + +func (RouteTargetInternetGateway) isRouteTargetValue() {} // RouteTargetDrop is drop matching traffic // @@ -5477,13 +5719,81 @@ type RouteTargetDrop struct { Type RouteTargetType `json:"type" yaml:"type"` } +func (RouteTargetDrop) isRouteTargetValue() {} + // RouteTarget is a `RouteTarget` describes the possible locations that traffic matching a route destination can // be sent. type RouteTarget struct { // Type is the type definition for a Type. Type RouteTargetType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value RouteTargetValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *RouteTarget) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator RouteTargetType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case RouteTargetTypeIp: + type value struct { + Value RouteTargetIp `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteTargetTypeVpc: + type value struct { + Value RouteTargetVpc `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteTargetTypeSubnet: + type value struct { + Value RouteTargetSubnet `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteTargetTypeInstance: + type value struct { + Value RouteTargetInstance `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteTargetTypeInternetGateway: + type value struct { + Value RouteTargetInternetGateway `json:"value"` + } + var val value + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val.Value + case RouteTargetTypeDrop: + var val RouteTargetDrop + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown RouteTarget discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // RouterRoute is a route defines a rule that governs where traffic should be sent based on its destination. @@ -7126,6 +7436,10 @@ type Utilization struct { Provisioned VirtualResourceCounts `json:"provisioned" yaml:"provisioned"` } +type ValueArrayValues interface { + isValueArrayValues() +} + // ValueArrayType is the type definition for a ValueArrayType. type ValueArrayType string @@ -7139,6 +7453,8 @@ type ValueArrayInteger struct { Values []int `json:"values" yaml:"values"` } +func (ValueArrayInteger) isValueArrayValues() {} + // ValueArrayDouble is the type definition for a ValueArrayDouble. // // Required fields: @@ -7149,6 +7465,8 @@ type ValueArrayDouble struct { Values []float64 `json:"values" yaml:"values"` } +func (ValueArrayDouble) isValueArrayValues() {} + // ValueArrayBoolean is the type definition for a ValueArrayBoolean. // // Required fields: @@ -7159,6 +7477,8 @@ type ValueArrayBoolean struct { Values []bool `json:"values" yaml:"values"` } +func (ValueArrayBoolean) isValueArrayValues() {} + // ValueArrayString is the type definition for a ValueArrayString. // // Required fields: @@ -7169,6 +7489,8 @@ type ValueArrayString struct { Values []string `json:"values" yaml:"values"` } +func (ValueArrayString) isValueArrayValues() {} + // ValueArrayIntegerDistribution is the type definition for a ValueArrayIntegerDistribution. // // Required fields: @@ -7179,6 +7501,8 @@ type ValueArrayIntegerDistribution struct { Values []Distributionint64 `json:"values" yaml:"values"` } +func (ValueArrayIntegerDistribution) isValueArrayValues() {} + // ValueArrayDoubleDistribution is the type definition for a ValueArrayDoubleDistribution. // // Required fields: @@ -7189,6 +7513,8 @@ type ValueArrayDoubleDistribution struct { Values []Distributiondouble `json:"values" yaml:"values"` } +func (ValueArrayDoubleDistribution) isValueArrayValues() {} + // ValueArray is list of data values for one timeseries. // // Each element is an option, where `None` represents a missing sample. @@ -7196,7 +7522,58 @@ type ValueArray struct { // Type is the type definition for a Type. Type ValueArrayType `json:"type,omitempty" yaml:"type,omitempty"` // Values is the type definition for a Values. - Values any `json:"values,omitempty" yaml:"values,omitempty"` + Values ValueArrayValues `json:"values,omitempty" yaml:"values,omitempty"` +} + +func (v *ValueArray) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator ValueArrayType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case ValueArrayTypeInteger: + var val ValueArrayInteger + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeDouble: + var val ValueArrayDouble + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeBoolean: + var val ValueArrayBoolean + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeString: + var val ValueArrayString + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeIntegerDistribution: + var val ValueArrayIntegerDistribution + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeDoubleDistribution: + var val ValueArrayDoubleDistribution + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Values = val + default: + return fmt.Errorf("unknown ValueArray discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // Values is a single list of values, for one dimension of a timeseries. @@ -7358,57 +7735,38 @@ type VpcFirewallRuleFilter struct { Protocols []VpcFirewallRuleProtocol `json:"protocols" yaml:"protocols"` } +type VpcFirewallRuleHostFilterValue interface { + isVpcFirewallRuleHostFilterValue() +} + +// VpcFirewallRuleHostFilterVpc is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleHostFilterVpc string + +func (VpcFirewallRuleHostFilterVpc) isVpcFirewallRuleHostFilterValue() {} + // VpcFirewallRuleHostFilterType is the type definition for a VpcFirewallRuleHostFilterType. type VpcFirewallRuleHostFilterType string -// VpcFirewallRuleHostFilterVpc is the rule applies to traffic from/to all instances in the VPC -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterVpc struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleHostFilterSubnet is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleHostFilterSubnet string -// VpcFirewallRuleHostFilterSubnet is the rule applies to traffic from/to all instances in the VPC Subnet -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterSubnet struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (VpcFirewallRuleHostFilterSubnet) isVpcFirewallRuleHostFilterValue() {} -// VpcFirewallRuleHostFilterInstance is the rule applies to traffic from/to this specific instance -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterInstance struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleHostFilterInstance is names must begin with a lower case ASCII letter, be composed exclusively +// of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, +// but they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleHostFilterInstance string -// VpcFirewallRuleHostFilterIp is the rule applies to traffic from/to a specific IP address -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterIp struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +func (VpcFirewallRuleHostFilterInstance) isVpcFirewallRuleHostFilterValue() {} + +// VpcFirewallRuleHostFilterIp is the type definition for a VpcFirewallRuleHostFilterIp. +type VpcFirewallRuleHostFilterIp string + +func (VpcFirewallRuleHostFilterIp) isVpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilterIpNet is the rule applies to traffic from/to a specific IP subnet // @@ -7420,6 +7778,8 @@ type VpcFirewallRuleHostFilterIpNet struct { Value IpNet `json:"value" yaml:"value"` } +func (VpcFirewallRuleHostFilterIpNet) isVpcFirewallRuleHostFilterValue() {} + // VpcFirewallRuleHostFilter is the `VpcFirewallRuleHostFilter` is used to filter traffic on the basis of // its source or destination host. type VpcFirewallRuleHostFilter struct { @@ -7428,7 +7788,52 @@ type VpcFirewallRuleHostFilter struct { // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They // can be at most 63 characters long. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value VpcFirewallRuleHostFilterValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *VpcFirewallRuleHostFilter) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator VpcFirewallRuleHostFilterType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case VpcFirewallRuleHostFilterTypeVpc: + var val VpcFirewallRuleHostFilterVpc + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeSubnet: + var val VpcFirewallRuleHostFilterSubnet + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeInstance: + var val VpcFirewallRuleHostFilterInstance + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeIp: + var val VpcFirewallRuleHostFilterIp + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeIpNet: + var val VpcFirewallRuleHostFilterIpNet + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown VpcFirewallRuleHostFilter discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // VpcFirewallRuleProtocolType is the type definition for a VpcFirewallRuleProtocolType. @@ -7471,57 +7876,38 @@ type VpcFirewallRuleProtocol struct { // VpcFirewallRuleStatus is the type definition for a VpcFirewallRuleStatus. type VpcFirewallRuleStatus string +type VpcFirewallRuleTargetValue interface { + isVpcFirewallRuleTargetValue() +} + +// VpcFirewallRuleTargetVpc is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleTargetVpc string + +func (VpcFirewallRuleTargetVpc) isVpcFirewallRuleTargetValue() {} + // VpcFirewallRuleTargetType is the type definition for a VpcFirewallRuleTargetType. type VpcFirewallRuleTargetType string -// VpcFirewallRuleTargetVpc is the rule applies to all instances in the VPC -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetVpc struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleTargetSubnet is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleTargetSubnet string -// VpcFirewallRuleTargetSubnet is the rule applies to all instances in the VPC Subnet -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetSubnet struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (VpcFirewallRuleTargetSubnet) isVpcFirewallRuleTargetValue() {} -// VpcFirewallRuleTargetInstance is the rule applies to this specific instance -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetInstance struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleTargetInstance is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleTargetInstance string -// VpcFirewallRuleTargetIp is the rule applies to a specific IP address -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetIp struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +func (VpcFirewallRuleTargetInstance) isVpcFirewallRuleTargetValue() {} + +// VpcFirewallRuleTargetIp is the type definition for a VpcFirewallRuleTargetIp. +type VpcFirewallRuleTargetIp string + +func (VpcFirewallRuleTargetIp) isVpcFirewallRuleTargetValue() {} // VpcFirewallRuleTargetIpNet is the rule applies to a specific IP subnet // @@ -7533,6 +7919,8 @@ type VpcFirewallRuleTargetIpNet struct { Value IpNet `json:"value" yaml:"value"` } +func (VpcFirewallRuleTargetIpNet) isVpcFirewallRuleTargetValue() {} + // VpcFirewallRuleTarget is a `VpcFirewallRuleTarget` is used to specify the set of instances to which a // firewall rule applies. You can target instances directly by name, or specify a VPC, VPC subnet, IP, or IP // subnet, which will apply the rule to traffic going to all matching instances. Targets are additive: the rule @@ -7543,7 +7931,52 @@ type VpcFirewallRuleTarget struct { // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They // can be at most 63 characters long. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value VpcFirewallRuleTargetValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *VpcFirewallRuleTarget) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator VpcFirewallRuleTargetType `json:"type"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case VpcFirewallRuleTargetTypeVpc: + var val VpcFirewallRuleTargetVpc + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeSubnet: + var val VpcFirewallRuleTargetSubnet + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeInstance: + var val VpcFirewallRuleTargetInstance + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeIp: + var val VpcFirewallRuleTargetIp + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeIpNet: + var val VpcFirewallRuleTargetIpNet + if err := json.Unmarshal(data, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown VpcFirewallRuleTarget discriminator value for type %s: %v", string(data), peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // VpcFirewallRuleUpdate is a single rule in a VPC firewall From 8c6215988935e82fac8156475d10b2a30321ac07 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 25 Nov 2025 10:09:13 -0500 Subject: [PATCH 2/6] Interface generation cleanup. --- internal/generate/types.go | 51 ++++++++++++++++++++++---------------- oxide/types.go | 18 +++++++------- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/internal/generate/types.go b/internal/generate/types.go index bbbadb0..fd70404 100644 --- a/internal/generate/types.go +++ b/internal/generate/types.go @@ -361,8 +361,11 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect fmt.Fprint(f, "}\n") } + // Write custom UnmarshalJSON method for oneOf types. if tt.DiscriminatorKey != "" && tt.VariantField != "" { fmt.Fprintf(f, "func (v *%s) UnmarshalJSON(data []byte) error {\n", tt.Name) + + // Check the discriminator to decide which type to unmarshal to. fmt.Fprintf(f, "\tvar peek struct {\n") fmt.Fprintf(f, "\t\tDiscriminator %s `json:\"%s\"`\n", tt.DiscriminatorType, tt.DiscriminatorKey) fmt.Fprintf(f, "\t}\n") @@ -371,10 +374,12 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect fmt.Fprintf(f, "\t}\n") fmt.Fprintf(f, "\tswitch peek.Discriminator {\n") + // Construct a case for each possible variant. for _, mapping := range tt.DiscriminatorMappings { fmt.Fprintf(f, "\tcase %s:\n", mapping.EnumConstant) - if slices.Contains([]string{"string", "int", "*bool"}, mapping.ObjectType) { + // For objects, unmarshal into the corresponding struct. For simple types, unmarshal into a temporary struct, then grab the value from it. + if isSimpleType(mapping.ObjectType) { fmt.Fprintf(f, "\t\ttype value struct {\n") fmt.Fprintf(f, "\t\t\tValue %s `json:\"%s\"`\n", mapping.ConcreteType, strings.ToLower(tt.VariantField)) fmt.Fprintf(f, "\t\t}\n") @@ -392,7 +397,7 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect } } fmt.Fprintf(f, "\tdefault:\n") - fmt.Fprintf(f, "\t\treturn fmt.Errorf(\"unknown %s discriminator value for %s %%s: %%v\", string(data), peek.Discriminator)\n", tt.Name, tt.DiscriminatorKey) + fmt.Fprintf(f, "\t\treturn fmt.Errorf(\"unknown %s discriminator value for %s: %%v\", peek.Discriminator)\n", tt.Name, tt.DiscriminatorKey) fmt.Fprintf(f, "\t}\n") fmt.Fprintf(f, "\tv.%s = peek.Discriminator\n", tt.DiscriminatorField) fmt.Fprintf(f, "\treturn nil\n") @@ -479,7 +484,7 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string case "string", "*bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64": typeTpl.Description = formatTypeDescription(typeName, s) - typeTpl.Type = ot + typeTpl.Type = strings.TrimPrefix(ot, "*") typeTpl.Name = typeName case "array": typeTpl.Description = formatTypeDescription(typeName, s) @@ -850,33 +855,29 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E // TODO: This is the only place that has an "additional name" at the end // TODO: This is where the "allOf" is being detected if len(variantFields) == 1 && v.Value.Properties[variantFields[0]] != nil { - variantType := getObjectType(v.Value.Properties[variantFields[0]].Value) - // if slices.Contains([]string{"string", "*bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", - // "uint16", "uint32", "uint64", "uintptr", "float32", "float64", "bytes"}, variantType) { - if !slices.Contains([]string{"array", "object", "all_of", "any_of", "one_of", "string_enum"}, variantType) { - tt, _ := populateTypeTemplates(name, v.Value.Properties[variantFields[0]].Value, enumFieldName, variantInterface) + variantField := variantFields[0] + variantType := getObjectType(v.Value.Properties[variantField].Value) + if isSimpleType(variantType) { + // Special case: process the variant field property separately + tt, _ := populateTypeTemplates(name, v.Value.Properties[variantField].Value, enumFieldName, variantInterface) typeTpls = append(typeTpls, tt...) - // enumTpls = append(enumTpls, et...) - fooTT, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) - // typeTpls = append(typeTpls, tt...) + parentTT, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) enumTpls = append(enumTpls, et...) - for idx, tt := range fooTT { - if strings.HasSuffix(tt.Name, "Type") { - fmt.Printf("DEBUG TT TYPE %d %s %s %+v\n", idx, name, enumFieldName, tt) + // Only include parent types with Type suffix + for _, tt := range parentTT { + if strings.HasSuffix(tt.Name, strcase.ToCamel(discriminator)) { typeTpls = append(typeTpls, tt) } } - } else { - tt, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) - typeTpls = append(typeTpls, tt...) - enumTpls = append(enumTpls, et...) + continue } - } else { - tt, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) - typeTpls = append(typeTpls, tt...) - enumTpls = append(enumTpls, et...) } + + // Normal case: process the parent schema + tt, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) + typeTpls = append(typeTpls, tt...) + enumTpls = append(enumTpls, et...) } // TODO: For now AllOf values within a OneOf are treated as enums @@ -958,3 +959,9 @@ func formatTypeDescription(name string, s *openapi3.Schema) string { } return fmt.Sprintf("// %s is the type definition for a %s.", name, name) } + +func isSimpleType(t string) bool { + simpleTypes := []string{"string", "*bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", + "uint16", "uint32", "uint64", "uintptr", "float32", "float64"} + return slices.Contains(simpleTypes, t) +} diff --git a/oxide/types.go b/oxide/types.go index 4775e94..8a64a33 100644 --- a/oxide/types.go +++ b/oxide/types.go @@ -1929,7 +1929,7 @@ type DatumDatum interface { } // DatumBool is the type definition for a DatumBool. -type DatumBool *bool +type DatumBool bool func (DatumBool) isDatumDatum() {} @@ -2442,7 +2442,7 @@ func (v *Datum) UnmarshalJSON(data []byte) error { } v.Datum = val default: - return fmt.Errorf("unknown Datum discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown Datum discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil @@ -3083,7 +3083,7 @@ type FieldValueUuid string func (FieldValueUuid) isFieldValueValue() {} // FieldValueBool is the type definition for a FieldValueBool. -type FieldValueBool *bool +type FieldValueBool bool func (FieldValueBool) isFieldValueValue() {} @@ -3212,7 +3212,7 @@ func (v *FieldValue) UnmarshalJSON(data []byte) error { } v.Value = val.Value default: - return fmt.Errorf("unknown FieldValue discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown FieldValue discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil @@ -5665,7 +5665,7 @@ func (v *RouteDestination) UnmarshalJSON(data []byte) error { } v.Value = val.Value default: - return fmt.Errorf("unknown RouteDestination discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown RouteDestination discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil @@ -5790,7 +5790,7 @@ func (v *RouteTarget) UnmarshalJSON(data []byte) error { } v.Value = val default: - return fmt.Errorf("unknown RouteTarget discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown RouteTarget discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil @@ -7570,7 +7570,7 @@ func (v *ValueArray) UnmarshalJSON(data []byte) error { } v.Values = val default: - return fmt.Errorf("unknown ValueArray discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown ValueArray discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil @@ -7830,7 +7830,7 @@ func (v *VpcFirewallRuleHostFilter) UnmarshalJSON(data []byte) error { } v.Value = val default: - return fmt.Errorf("unknown VpcFirewallRuleHostFilter discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown VpcFirewallRuleHostFilter discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil @@ -7973,7 +7973,7 @@ func (v *VpcFirewallRuleTarget) UnmarshalJSON(data []byte) error { } v.Value = val default: - return fmt.Errorf("unknown VpcFirewallRuleTarget discriminator value for type %s: %v", string(data), peek.Discriminator) + return fmt.Errorf("unknown VpcFirewallRuleTarget discriminator value for type: %v", peek.Discriminator) } v.Type = peek.Discriminator return nil From f372888c73846ef3dde291896995259852d5a301 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 25 Nov 2025 10:18:52 -0500 Subject: [PATCH 3/6] Interface types: fix tests. --- internal/generate/types_test.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/internal/generate/types_test.go b/internal/generate/types_test.go index 8059762..7b2b30f 100644 --- a/internal/generate/types_test.go +++ b/internal/generate/types_test.go @@ -273,7 +273,10 @@ func Test_createOneOf(t *testing.T) { }, }, { - Description: "// ImageSource is the source of the underlying image.", Name: "ImageSource", Type: "struct", Fields: []TypeFields{ + Description: "// ImageSource is the source of the underlying image.", + Name: "ImageSource", + Type: "struct", + Fields: []TypeFields{ { Description: "// Type is the type definition for a Type.", Name: "Type", Type: "ImageSourceType", SerializationInfo: "`json:\"type,omitempty\" yaml:\"type,omitempty\"`", }, @@ -284,6 +287,22 @@ func Test_createOneOf(t *testing.T) { Description: "// Id is the type definition for a Id.", Name: "Id", Type: "string", SerializationInfo: "`json:\"id,omitempty\" yaml:\"id,omitempty\"`", }, }, + DiscriminatorKey: "type", + DiscriminatorField: "Type", + DiscriminatorType: "ImageSourceType", + DiscriminatorMappings: []DiscriminatorMapping{ + { + EnumConstant: "ImageSourceTypeUrl", + ConcreteType: "ImageSourceUrl", + ObjectType: "", + }, + { + EnumConstant: "ImageSourceTypeSnapshot", + ConcreteType: "ImageSourceSnapshot", + ObjectType: "", + }, + }, + VariantField: "", }, }, want1: []EnumTemplate{ From 3605de01ae525df007b45ee605be35cf05cae81a Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 25 Nov 2025 12:18:35 -0500 Subject: [PATCH 4/6] Drop unused code. --- internal/generate/utils.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/internal/generate/utils.go b/internal/generate/utils.go index 8285fa8..4801f0d 100644 --- a/internal/generate/utils.go +++ b/internal/generate/utils.go @@ -255,15 +255,6 @@ func isNumericType(str string) bool { return slices.Contains(numTypes, str) } -func allItemsAreSame[T comparable](a []T) bool { - for _, v := range a { - if v != a[0] { - return false - } - } - return true -} - // sortedKeys returns a []string of sorted keys from a map. Used to ensure // deterministic ordering of generated code. func sortedKeys[T any](m map[string]T) []string { From 5ed6c4368ef085f31f3cc80a917571059c9f4d80 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 1 Dec 2025 12:38:41 -0500 Subject: [PATCH 5/6] Make variant interfaces private. --- internal/generate/types.go | 3 +- oxide/types.go | 174 ++++++++++++++++++------------------- 2 files changed, 89 insertions(+), 88 deletions(-) diff --git a/internal/generate/types.go b/internal/generate/types.go index fd70404..6ed9934 100644 --- a/internal/generate/types.go +++ b/internal/generate/types.go @@ -760,7 +760,8 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E variantInterface := "" if len(variantFields) == 1 && len(variantTypes) == 1 { variantField = strcase.ToCamel(variantFields[0]) - variantInterface = fmt.Sprintf("%s%s", typeName, strcase.ToCamel(variantTypes[0])) + // Note: the variant interface is only used to define the tagged enum, and not of interest to users, so we make it private. + variantInterface = fmt.Sprintf("%s%s", strcase.ToLowerCamel(typeName), strcase.ToCamel(variantTypes[0])) typeTpls = append(typeTpls, TypeTemplate{ Name: variantInterface, Type: "interface", diff --git a/oxide/types.go b/oxide/types.go index 8a64a33..b3e2d1a 100644 --- a/oxide/types.go +++ b/oxide/types.go @@ -1924,14 +1924,14 @@ type CurrentUser struct { SiloName Name `json:"silo_name" yaml:"silo_name"` } -type DatumDatum interface { - isDatumDatum() +type datumDatum interface { + isdatumDatum() } // DatumBool is the type definition for a DatumBool. type DatumBool bool -func (DatumBool) isDatumDatum() {} +func (DatumBool) isdatumDatum() {} // DatumType is the type definition for a DatumType. type DatumType string @@ -1939,57 +1939,57 @@ type DatumType string // DatumI8 is the type definition for a DatumI8. type DatumI8 int8 -func (DatumI8) isDatumDatum() {} +func (DatumI8) isdatumDatum() {} // DatumU8 is the type definition for a DatumU8. type DatumU8 uint8 -func (DatumU8) isDatumDatum() {} +func (DatumU8) isdatumDatum() {} // DatumI16 is the type definition for a DatumI16. type DatumI16 int16 -func (DatumI16) isDatumDatum() {} +func (DatumI16) isdatumDatum() {} // DatumU16 is the type definition for a DatumU16. type DatumU16 uint16 -func (DatumU16) isDatumDatum() {} +func (DatumU16) isdatumDatum() {} // DatumI32 is the type definition for a DatumI32. type DatumI32 int32 -func (DatumI32) isDatumDatum() {} +func (DatumI32) isdatumDatum() {} // DatumU32 is the type definition for a DatumU32. type DatumU32 uint32 -func (DatumU32) isDatumDatum() {} +func (DatumU32) isdatumDatum() {} // DatumI64 is the type definition for a DatumI64. type DatumI64 int64 -func (DatumI64) isDatumDatum() {} +func (DatumI64) isdatumDatum() {} // DatumU64 is the type definition for a DatumU64. type DatumU64 uint64 -func (DatumU64) isDatumDatum() {} +func (DatumU64) isdatumDatum() {} // DatumF32 is the type definition for a DatumF32. type DatumF32 float64 -func (DatumF32) isDatumDatum() {} +func (DatumF32) isdatumDatum() {} // DatumF64 is the type definition for a DatumF64. type DatumF64 float64 -func (DatumF64) isDatumDatum() {} +func (DatumF64) isdatumDatum() {} // DatumString is the type definition for a DatumString. type DatumString string -func (DatumString) isDatumDatum() {} +func (DatumString) isdatumDatum() {} // DatumBytes is the type definition for a DatumBytes. // @@ -2001,7 +2001,7 @@ type DatumBytes struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumBytes) isDatumDatum() {} +func (DatumBytes) isdatumDatum() {} // DatumCumulativeI64 is the type definition for a DatumCumulativeI64. // @@ -2014,7 +2014,7 @@ type DatumCumulativeI64 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumCumulativeI64) isDatumDatum() {} +func (DatumCumulativeI64) isdatumDatum() {} // DatumCumulativeU64 is the type definition for a DatumCumulativeU64. // @@ -2027,7 +2027,7 @@ type DatumCumulativeU64 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumCumulativeU64) isDatumDatum() {} +func (DatumCumulativeU64) isdatumDatum() {} // DatumCumulativeF32 is the type definition for a DatumCumulativeF32. // @@ -2040,7 +2040,7 @@ type DatumCumulativeF32 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumCumulativeF32) isDatumDatum() {} +func (DatumCumulativeF32) isdatumDatum() {} // DatumCumulativeF64 is the type definition for a DatumCumulativeF64. // @@ -2053,7 +2053,7 @@ type DatumCumulativeF64 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumCumulativeF64) isDatumDatum() {} +func (DatumCumulativeF64) isdatumDatum() {} // DatumHistogramI8 is the type definition for a DatumHistogramI8. // @@ -2072,7 +2072,7 @@ type DatumHistogramI8 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramI8) isDatumDatum() {} +func (DatumHistogramI8) isdatumDatum() {} // DatumHistogramU8 is the type definition for a DatumHistogramU8. // @@ -2091,7 +2091,7 @@ type DatumHistogramU8 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramU8) isDatumDatum() {} +func (DatumHistogramU8) isdatumDatum() {} // DatumHistogramI16 is the type definition for a DatumHistogramI16. // @@ -2110,7 +2110,7 @@ type DatumHistogramI16 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramI16) isDatumDatum() {} +func (DatumHistogramI16) isdatumDatum() {} // DatumHistogramU16 is the type definition for a DatumHistogramU16. // @@ -2129,7 +2129,7 @@ type DatumHistogramU16 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramU16) isDatumDatum() {} +func (DatumHistogramU16) isdatumDatum() {} // DatumHistogramI32 is the type definition for a DatumHistogramI32. // @@ -2148,7 +2148,7 @@ type DatumHistogramI32 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramI32) isDatumDatum() {} +func (DatumHistogramI32) isdatumDatum() {} // DatumHistogramU32 is the type definition for a DatumHistogramU32. // @@ -2167,7 +2167,7 @@ type DatumHistogramU32 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramU32) isDatumDatum() {} +func (DatumHistogramU32) isdatumDatum() {} // DatumHistogramI64 is the type definition for a DatumHistogramI64. // @@ -2186,7 +2186,7 @@ type DatumHistogramI64 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramI64) isDatumDatum() {} +func (DatumHistogramI64) isdatumDatum() {} // DatumHistogramU64 is the type definition for a DatumHistogramU64. // @@ -2205,7 +2205,7 @@ type DatumHistogramU64 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramU64) isDatumDatum() {} +func (DatumHistogramU64) isdatumDatum() {} // DatumHistogramF32 is the type definition for a DatumHistogramF32. // @@ -2224,7 +2224,7 @@ type DatumHistogramF32 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramF32) isDatumDatum() {} +func (DatumHistogramF32) isdatumDatum() {} // DatumHistogramF64 is the type definition for a DatumHistogramF64. // @@ -2243,7 +2243,7 @@ type DatumHistogramF64 struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumHistogramF64) isDatumDatum() {} +func (DatumHistogramF64) isdatumDatum() {} // DatumMissing is the type definition for a DatumMissing. // @@ -2255,12 +2255,12 @@ type DatumMissing struct { Type DatumType `json:"type" yaml:"type"` } -func (DatumMissing) isDatumDatum() {} +func (DatumMissing) isdatumDatum() {} // Datum is a `Datum` is a single sampled data point from a metric. type Datum struct { // Datum is the type definition for a Datum. - Datum DatumDatum `json:"datum,omitempty" yaml:"datum,omitempty"` + Datum datumDatum `json:"datum,omitempty" yaml:"datum,omitempty"` // Type is the type definition for a Type. Type DatumType `json:"type,omitempty" yaml:"type,omitempty"` } @@ -3020,14 +3020,14 @@ type FieldSource string // FieldType is the `FieldType` identifies the data type of a target or metric field. type FieldType string -type FieldValueValue interface { - isFieldValueValue() +type fieldValueValue interface { + isfieldValueValue() } // FieldValueString is the type definition for a FieldValueString. type FieldValueString string -func (FieldValueString) isFieldValueValue() {} +func (FieldValueString) isfieldValueValue() {} // FieldValueType is the type definition for a FieldValueType. type FieldValueType string @@ -3035,64 +3035,64 @@ type FieldValueType string // FieldValueI8 is the type definition for a FieldValueI8. type FieldValueI8 int8 -func (FieldValueI8) isFieldValueValue() {} +func (FieldValueI8) isfieldValueValue() {} // FieldValueU8 is the type definition for a FieldValueU8. type FieldValueU8 uint8 -func (FieldValueU8) isFieldValueValue() {} +func (FieldValueU8) isfieldValueValue() {} // FieldValueI16 is the type definition for a FieldValueI16. type FieldValueI16 int16 -func (FieldValueI16) isFieldValueValue() {} +func (FieldValueI16) isfieldValueValue() {} // FieldValueU16 is the type definition for a FieldValueU16. type FieldValueU16 uint16 -func (FieldValueU16) isFieldValueValue() {} +func (FieldValueU16) isfieldValueValue() {} // FieldValueI32 is the type definition for a FieldValueI32. type FieldValueI32 int32 -func (FieldValueI32) isFieldValueValue() {} +func (FieldValueI32) isfieldValueValue() {} // FieldValueU32 is the type definition for a FieldValueU32. type FieldValueU32 uint32 -func (FieldValueU32) isFieldValueValue() {} +func (FieldValueU32) isfieldValueValue() {} // FieldValueI64 is the type definition for a FieldValueI64. type FieldValueI64 int64 -func (FieldValueI64) isFieldValueValue() {} +func (FieldValueI64) isfieldValueValue() {} // FieldValueU64 is the type definition for a FieldValueU64. type FieldValueU64 uint64 -func (FieldValueU64) isFieldValueValue() {} +func (FieldValueU64) isfieldValueValue() {} // FieldValueIpAddr is the type definition for a FieldValueIpAddr. type FieldValueIpAddr string -func (FieldValueIpAddr) isFieldValueValue() {} +func (FieldValueIpAddr) isfieldValueValue() {} // FieldValueUuid is the type definition for a FieldValueUuid. type FieldValueUuid string -func (FieldValueUuid) isFieldValueValue() {} +func (FieldValueUuid) isfieldValueValue() {} // FieldValueBool is the type definition for a FieldValueBool. type FieldValueBool bool -func (FieldValueBool) isFieldValueValue() {} +func (FieldValueBool) isfieldValueValue() {} // FieldValue is the `FieldValue` contains the value of a target or metric field. type FieldValue struct { // Type is the type definition for a Type. Type FieldValueType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value FieldValueValue `json:"value,omitempty" yaml:"value,omitempty"` + Value fieldValueValue `json:"value,omitempty" yaml:"value,omitempty"` } func (v *FieldValue) UnmarshalJSON(data []byte) error { @@ -5570,14 +5570,14 @@ type RouteConfig struct { Routes []Route `json:"routes" yaml:"routes"` } -type RouteDestinationValue interface { - isRouteDestinationValue() +type routeDestinationValue interface { + isrouteDestinationValue() } // RouteDestinationIp is the type definition for a RouteDestinationIp. type RouteDestinationIp string -func (RouteDestinationIp) isRouteDestinationValue() {} +func (RouteDestinationIp) isrouteDestinationValue() {} // RouteDestinationType is the type definition for a RouteDestinationType. type RouteDestinationType string @@ -5592,21 +5592,21 @@ type RouteDestinationIpNet struct { Value IpNet `json:"value" yaml:"value"` } -func (RouteDestinationIpNet) isRouteDestinationValue() {} +func (RouteDestinationIpNet) isrouteDestinationValue() {} // RouteDestinationVpc is names must begin with a lower case ASCII letter, be composed exclusively of lowercase // ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may // contain a UUID. They can be at most 63 characters long. type RouteDestinationVpc string -func (RouteDestinationVpc) isRouteDestinationValue() {} +func (RouteDestinationVpc) isrouteDestinationValue() {} // RouteDestinationSubnet is names must begin with a lower case ASCII letter, be composed exclusively of // lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but // they may contain a UUID. They can be at most 63 characters long. type RouteDestinationSubnet string -func (RouteDestinationSubnet) isRouteDestinationValue() {} +func (RouteDestinationSubnet) isrouteDestinationValue() {} // RouteDestination is a `RouteDestination` is used to match traffic with a routing rule based on the destination // of that traffic. @@ -5617,7 +5617,7 @@ type RouteDestination struct { // Type is the type definition for a Type. Type RouteDestinationType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value RouteDestinationValue `json:"value,omitempty" yaml:"value,omitempty"` + Value routeDestinationValue `json:"value,omitempty" yaml:"value,omitempty"` } func (v *RouteDestination) UnmarshalJSON(data []byte) error { @@ -5671,14 +5671,14 @@ func (v *RouteDestination) UnmarshalJSON(data []byte) error { return nil } -type RouteTargetValue interface { - isRouteTargetValue() +type routeTargetValue interface { + isrouteTargetValue() } // RouteTargetIp is the type definition for a RouteTargetIp. type RouteTargetIp string -func (RouteTargetIp) isRouteTargetValue() {} +func (RouteTargetIp) isrouteTargetValue() {} // RouteTargetType is the type definition for a RouteTargetType. type RouteTargetType string @@ -5688,28 +5688,28 @@ type RouteTargetType string // UUID. They can be at most 63 characters long. type RouteTargetVpc string -func (RouteTargetVpc) isRouteTargetValue() {} +func (RouteTargetVpc) isrouteTargetValue() {} // RouteTargetSubnet is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, // uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a // UUID. They can be at most 63 characters long. type RouteTargetSubnet string -func (RouteTargetSubnet) isRouteTargetValue() {} +func (RouteTargetSubnet) isrouteTargetValue() {} // RouteTargetInstance is names must begin with a lower case ASCII letter, be composed exclusively of lowercase // ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may // contain a UUID. They can be at most 63 characters long. type RouteTargetInstance string -func (RouteTargetInstance) isRouteTargetValue() {} +func (RouteTargetInstance) isrouteTargetValue() {} // RouteTargetInternetGateway is names must begin with a lower case ASCII letter, be composed exclusively of // lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but // they may contain a UUID. They can be at most 63 characters long. type RouteTargetInternetGateway string -func (RouteTargetInternetGateway) isRouteTargetValue() {} +func (RouteTargetInternetGateway) isrouteTargetValue() {} // RouteTargetDrop is drop matching traffic // @@ -5719,7 +5719,7 @@ type RouteTargetDrop struct { Type RouteTargetType `json:"type" yaml:"type"` } -func (RouteTargetDrop) isRouteTargetValue() {} +func (RouteTargetDrop) isrouteTargetValue() {} // RouteTarget is a `RouteTarget` describes the possible locations that traffic matching a route destination can // be sent. @@ -5727,7 +5727,7 @@ type RouteTarget struct { // Type is the type definition for a Type. Type RouteTargetType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value RouteTargetValue `json:"value,omitempty" yaml:"value,omitempty"` + Value routeTargetValue `json:"value,omitempty" yaml:"value,omitempty"` } func (v *RouteTarget) UnmarshalJSON(data []byte) error { @@ -7436,8 +7436,8 @@ type Utilization struct { Provisioned VirtualResourceCounts `json:"provisioned" yaml:"provisioned"` } -type ValueArrayValues interface { - isValueArrayValues() +type valueArrayValues interface { + isvalueArrayValues() } // ValueArrayType is the type definition for a ValueArrayType. @@ -7453,7 +7453,7 @@ type ValueArrayInteger struct { Values []int `json:"values" yaml:"values"` } -func (ValueArrayInteger) isValueArrayValues() {} +func (ValueArrayInteger) isvalueArrayValues() {} // ValueArrayDouble is the type definition for a ValueArrayDouble. // @@ -7465,7 +7465,7 @@ type ValueArrayDouble struct { Values []float64 `json:"values" yaml:"values"` } -func (ValueArrayDouble) isValueArrayValues() {} +func (ValueArrayDouble) isvalueArrayValues() {} // ValueArrayBoolean is the type definition for a ValueArrayBoolean. // @@ -7477,7 +7477,7 @@ type ValueArrayBoolean struct { Values []bool `json:"values" yaml:"values"` } -func (ValueArrayBoolean) isValueArrayValues() {} +func (ValueArrayBoolean) isvalueArrayValues() {} // ValueArrayString is the type definition for a ValueArrayString. // @@ -7489,7 +7489,7 @@ type ValueArrayString struct { Values []string `json:"values" yaml:"values"` } -func (ValueArrayString) isValueArrayValues() {} +func (ValueArrayString) isvalueArrayValues() {} // ValueArrayIntegerDistribution is the type definition for a ValueArrayIntegerDistribution. // @@ -7501,7 +7501,7 @@ type ValueArrayIntegerDistribution struct { Values []Distributionint64 `json:"values" yaml:"values"` } -func (ValueArrayIntegerDistribution) isValueArrayValues() {} +func (ValueArrayIntegerDistribution) isvalueArrayValues() {} // ValueArrayDoubleDistribution is the type definition for a ValueArrayDoubleDistribution. // @@ -7513,7 +7513,7 @@ type ValueArrayDoubleDistribution struct { Values []Distributiondouble `json:"values" yaml:"values"` } -func (ValueArrayDoubleDistribution) isValueArrayValues() {} +func (ValueArrayDoubleDistribution) isvalueArrayValues() {} // ValueArray is list of data values for one timeseries. // @@ -7522,7 +7522,7 @@ type ValueArray struct { // Type is the type definition for a Type. Type ValueArrayType `json:"type,omitempty" yaml:"type,omitempty"` // Values is the type definition for a Values. - Values ValueArrayValues `json:"values,omitempty" yaml:"values,omitempty"` + Values valueArrayValues `json:"values,omitempty" yaml:"values,omitempty"` } func (v *ValueArray) UnmarshalJSON(data []byte) error { @@ -7735,8 +7735,8 @@ type VpcFirewallRuleFilter struct { Protocols []VpcFirewallRuleProtocol `json:"protocols" yaml:"protocols"` } -type VpcFirewallRuleHostFilterValue interface { - isVpcFirewallRuleHostFilterValue() +type vpcFirewallRuleHostFilterValue interface { + isvpcFirewallRuleHostFilterValue() } // VpcFirewallRuleHostFilterVpc is names must begin with a lower case ASCII letter, be composed exclusively of @@ -7744,7 +7744,7 @@ type VpcFirewallRuleHostFilterValue interface { // they may contain a UUID. They can be at most 63 characters long. type VpcFirewallRuleHostFilterVpc string -func (VpcFirewallRuleHostFilterVpc) isVpcFirewallRuleHostFilterValue() {} +func (VpcFirewallRuleHostFilterVpc) isvpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilterType is the type definition for a VpcFirewallRuleHostFilterType. type VpcFirewallRuleHostFilterType string @@ -7754,19 +7754,19 @@ type VpcFirewallRuleHostFilterType string // they may contain a UUID. They can be at most 63 characters long. type VpcFirewallRuleHostFilterSubnet string -func (VpcFirewallRuleHostFilterSubnet) isVpcFirewallRuleHostFilterValue() {} +func (VpcFirewallRuleHostFilterSubnet) isvpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilterInstance is names must begin with a lower case ASCII letter, be composed exclusively // of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, // but they may contain a UUID. They can be at most 63 characters long. type VpcFirewallRuleHostFilterInstance string -func (VpcFirewallRuleHostFilterInstance) isVpcFirewallRuleHostFilterValue() {} +func (VpcFirewallRuleHostFilterInstance) isvpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilterIp is the type definition for a VpcFirewallRuleHostFilterIp. type VpcFirewallRuleHostFilterIp string -func (VpcFirewallRuleHostFilterIp) isVpcFirewallRuleHostFilterValue() {} +func (VpcFirewallRuleHostFilterIp) isvpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilterIpNet is the rule applies to traffic from/to a specific IP subnet // @@ -7778,7 +7778,7 @@ type VpcFirewallRuleHostFilterIpNet struct { Value IpNet `json:"value" yaml:"value"` } -func (VpcFirewallRuleHostFilterIpNet) isVpcFirewallRuleHostFilterValue() {} +func (VpcFirewallRuleHostFilterIpNet) isvpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilter is the `VpcFirewallRuleHostFilter` is used to filter traffic on the basis of // its source or destination host. @@ -7788,7 +7788,7 @@ type VpcFirewallRuleHostFilter struct { // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They // can be at most 63 characters long. - Value VpcFirewallRuleHostFilterValue `json:"value,omitempty" yaml:"value,omitempty"` + Value vpcFirewallRuleHostFilterValue `json:"value,omitempty" yaml:"value,omitempty"` } func (v *VpcFirewallRuleHostFilter) UnmarshalJSON(data []byte) error { @@ -7876,8 +7876,8 @@ type VpcFirewallRuleProtocol struct { // VpcFirewallRuleStatus is the type definition for a VpcFirewallRuleStatus. type VpcFirewallRuleStatus string -type VpcFirewallRuleTargetValue interface { - isVpcFirewallRuleTargetValue() +type vpcFirewallRuleTargetValue interface { + isvpcFirewallRuleTargetValue() } // VpcFirewallRuleTargetVpc is names must begin with a lower case ASCII letter, be composed exclusively of @@ -7885,7 +7885,7 @@ type VpcFirewallRuleTargetValue interface { // they may contain a UUID. They can be at most 63 characters long. type VpcFirewallRuleTargetVpc string -func (VpcFirewallRuleTargetVpc) isVpcFirewallRuleTargetValue() {} +func (VpcFirewallRuleTargetVpc) isvpcFirewallRuleTargetValue() {} // VpcFirewallRuleTargetType is the type definition for a VpcFirewallRuleTargetType. type VpcFirewallRuleTargetType string @@ -7895,19 +7895,19 @@ type VpcFirewallRuleTargetType string // they may contain a UUID. They can be at most 63 characters long. type VpcFirewallRuleTargetSubnet string -func (VpcFirewallRuleTargetSubnet) isVpcFirewallRuleTargetValue() {} +func (VpcFirewallRuleTargetSubnet) isvpcFirewallRuleTargetValue() {} // VpcFirewallRuleTargetInstance is names must begin with a lower case ASCII letter, be composed exclusively of // lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but // they may contain a UUID. They can be at most 63 characters long. type VpcFirewallRuleTargetInstance string -func (VpcFirewallRuleTargetInstance) isVpcFirewallRuleTargetValue() {} +func (VpcFirewallRuleTargetInstance) isvpcFirewallRuleTargetValue() {} // VpcFirewallRuleTargetIp is the type definition for a VpcFirewallRuleTargetIp. type VpcFirewallRuleTargetIp string -func (VpcFirewallRuleTargetIp) isVpcFirewallRuleTargetValue() {} +func (VpcFirewallRuleTargetIp) isvpcFirewallRuleTargetValue() {} // VpcFirewallRuleTargetIpNet is the rule applies to a specific IP subnet // @@ -7919,7 +7919,7 @@ type VpcFirewallRuleTargetIpNet struct { Value IpNet `json:"value" yaml:"value"` } -func (VpcFirewallRuleTargetIpNet) isVpcFirewallRuleTargetValue() {} +func (VpcFirewallRuleTargetIpNet) isvpcFirewallRuleTargetValue() {} // VpcFirewallRuleTarget is a `VpcFirewallRuleTarget` is used to specify the set of instances to which a // firewall rule applies. You can target instances directly by name, or specify a VPC, VPC subnet, IP, or IP @@ -7931,7 +7931,7 @@ type VpcFirewallRuleTarget struct { // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They // can be at most 63 characters long. - Value VpcFirewallRuleTargetValue `json:"value,omitempty" yaml:"value,omitempty"` + Value vpcFirewallRuleTargetValue `json:"value,omitempty" yaml:"value,omitempty"` } func (v *VpcFirewallRuleTarget) UnmarshalJSON(data []byte) error { From 4e73d8af8fb936fb35f4b445a28b2ab9d30d0248 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 1 Dec 2025 14:51:28 -0500 Subject: [PATCH 6/6] Only unmarshal oneOf structs once. --- internal/generate/types.go | 12 +- oxide/types.go | 292 +++++++++++++++---------------------- 2 files changed, 123 insertions(+), 181 deletions(-) diff --git a/internal/generate/types.go b/internal/generate/types.go index 6ed9934..59d3e2b 100644 --- a/internal/generate/types.go +++ b/internal/generate/types.go @@ -368,6 +368,7 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect // Check the discriminator to decide which type to unmarshal to. fmt.Fprintf(f, "\tvar peek struct {\n") fmt.Fprintf(f, "\t\tDiscriminator %s `json:\"%s\"`\n", tt.DiscriminatorType, tt.DiscriminatorKey) + fmt.Fprintf(f, "\t\tValue json.RawMessage `json:\"%s\"`\n", strings.ToLower(tt.VariantField)) fmt.Fprintf(f, "\t}\n") fmt.Fprintf(f, "\tif err := json.Unmarshal(data, &peek); err != nil {\n") fmt.Fprintf(f, "\t\treturn err\n") @@ -380,17 +381,14 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect // For objects, unmarshal into the corresponding struct. For simple types, unmarshal into a temporary struct, then grab the value from it. if isSimpleType(mapping.ObjectType) { - fmt.Fprintf(f, "\t\ttype value struct {\n") - fmt.Fprintf(f, "\t\t\tValue %s `json:\"%s\"`\n", mapping.ConcreteType, strings.ToLower(tt.VariantField)) - fmt.Fprintf(f, "\t\t}\n") - fmt.Fprintf(f, "\t\tvar val value\n") - fmt.Fprintf(f, "\t\tif err := json.Unmarshal(data, &val); err != nil {\n") + fmt.Fprintf(f, "\t\tvar val %s\n", mapping.ConcreteType) + fmt.Fprintf(f, "\t\tif err := json.Unmarshal(peek.Value, &val); err != nil {\n") fmt.Fprintf(f, "\t\t\treturn err\n") fmt.Fprintf(f, "\t\t}\n") - fmt.Fprintf(f, "\tv.%s = val.Value\n", tt.VariantField) + fmt.Fprintf(f, "\tv.%s = val\n", tt.VariantField) } else { fmt.Fprintf(f, "\t\tvar val %s\n", mapping.ConcreteType) - fmt.Fprintf(f, "\t\tif err := json.Unmarshal(data, &val); err != nil {\n") + fmt.Fprintf(f, "\t\tif err := json.Unmarshal(peek.Value, &val); err != nil {\n") fmt.Fprintf(f, "\t\t\treturn err\n") fmt.Fprintf(f, "\t\t}\n") fmt.Fprintf(f, "\tv.%s = val\n", tt.VariantField) diff --git a/oxide/types.go b/oxide/types.go index b3e2d1a..2630389 100644 --- a/oxide/types.go +++ b/oxide/types.go @@ -2267,7 +2267,8 @@ type Datum struct { func (v *Datum) UnmarshalJSON(data []byte) error { var peek struct { - Discriminator DatumType `json:"type"` + Discriminator DatumType `json:"type"` + Value json.RawMessage `json:"datum"` } if err := json.Unmarshal(data, &peek); err != nil { return err @@ -2275,169 +2276,169 @@ func (v *Datum) UnmarshalJSON(data []byte) error { switch peek.Discriminator { case DatumTypeBool: var val DatumBool - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeI8: var val DatumI8 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeU8: var val DatumU8 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeI16: var val DatumI16 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeU16: var val DatumU16 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeI32: var val DatumI32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeU32: var val DatumU32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeI64: var val DatumI64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeU64: var val DatumU64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeF32: var val DatumF32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeF64: var val DatumF64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeString: var val DatumString - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeBytes: var val DatumBytes - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeCumulativeI64: var val DatumCumulativeI64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeCumulativeU64: var val DatumCumulativeU64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeCumulativeF32: var val DatumCumulativeF32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeCumulativeF64: var val DatumCumulativeF64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramI8: var val DatumHistogramI8 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramU8: var val DatumHistogramU8 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramI16: var val DatumHistogramI16 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramU16: var val DatumHistogramU16 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramI32: var val DatumHistogramI32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramU32: var val DatumHistogramU32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramI64: var val DatumHistogramI64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramU64: var val DatumHistogramU64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramF32: var val DatumHistogramF32 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeHistogramF64: var val DatumHistogramF64 - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val case DatumTypeMissing: var val DatumMissing - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Datum = val @@ -3097,120 +3098,85 @@ type FieldValue struct { func (v *FieldValue) UnmarshalJSON(data []byte) error { var peek struct { - Discriminator FieldValueType `json:"type"` + Discriminator FieldValueType `json:"type"` + Value json.RawMessage `json:"value"` } if err := json.Unmarshal(data, &peek); err != nil { return err } switch peek.Discriminator { case FieldValueTypeString: - type value struct { - Value FieldValueString `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueString + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeI8: - type value struct { - Value FieldValueI8 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueI8 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeU8: - type value struct { - Value FieldValueU8 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueU8 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeI16: - type value struct { - Value FieldValueI16 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueI16 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeU16: - type value struct { - Value FieldValueU16 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueU16 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeI32: - type value struct { - Value FieldValueI32 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueI32 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeU32: - type value struct { - Value FieldValueU32 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueU32 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeI64: - type value struct { - Value FieldValueI64 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueI64 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeU64: - type value struct { - Value FieldValueU64 `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueU64 + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeIpAddr: - type value struct { - Value FieldValueIpAddr `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueIpAddr + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeUuid: - type value struct { - Value FieldValueUuid `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueUuid + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case FieldValueTypeBool: - type value struct { - Value FieldValueBool `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val FieldValueBool + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val default: return fmt.Errorf("unknown FieldValue discriminator value for type: %v", peek.Discriminator) } @@ -5623,47 +5589,36 @@ type RouteDestination struct { func (v *RouteDestination) UnmarshalJSON(data []byte) error { var peek struct { Discriminator RouteDestinationType `json:"type"` + Value json.RawMessage `json:"value"` } if err := json.Unmarshal(data, &peek); err != nil { return err } switch peek.Discriminator { case RouteDestinationTypeIp: - type value struct { - Value RouteDestinationIp `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteDestinationIp + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteDestinationTypeIpNet: - type value struct { - Value RouteDestinationIpNet `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteDestinationIpNet + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteDestinationTypeVpc: - type value struct { - Value RouteDestinationVpc `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteDestinationVpc + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteDestinationTypeSubnet: - type value struct { - Value RouteDestinationSubnet `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteDestinationSubnet + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val default: return fmt.Errorf("unknown RouteDestination discriminator value for type: %v", peek.Discriminator) } @@ -5733,59 +5688,45 @@ type RouteTarget struct { func (v *RouteTarget) UnmarshalJSON(data []byte) error { var peek struct { Discriminator RouteTargetType `json:"type"` + Value json.RawMessage `json:"value"` } if err := json.Unmarshal(data, &peek); err != nil { return err } switch peek.Discriminator { case RouteTargetTypeIp: - type value struct { - Value RouteTargetIp `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteTargetIp + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteTargetTypeVpc: - type value struct { - Value RouteTargetVpc `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteTargetVpc + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteTargetTypeSubnet: - type value struct { - Value RouteTargetSubnet `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteTargetSubnet + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteTargetTypeInstance: - type value struct { - Value RouteTargetInstance `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteTargetInstance + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteTargetTypeInternetGateway: - type value struct { - Value RouteTargetInternetGateway `json:"value"` - } - var val value - if err := json.Unmarshal(data, &val); err != nil { + var val RouteTargetInternetGateway + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } - v.Value = val.Value + v.Value = val case RouteTargetTypeDrop: var val RouteTargetDrop - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val @@ -7527,7 +7468,8 @@ type ValueArray struct { func (v *ValueArray) UnmarshalJSON(data []byte) error { var peek struct { - Discriminator ValueArrayType `json:"type"` + Discriminator ValueArrayType `json:"type"` + Value json.RawMessage `json:"values"` } if err := json.Unmarshal(data, &peek); err != nil { return err @@ -7535,37 +7477,37 @@ func (v *ValueArray) UnmarshalJSON(data []byte) error { switch peek.Discriminator { case ValueArrayTypeInteger: var val ValueArrayInteger - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Values = val case ValueArrayTypeDouble: var val ValueArrayDouble - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Values = val case ValueArrayTypeBoolean: var val ValueArrayBoolean - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Values = val case ValueArrayTypeString: var val ValueArrayString - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Values = val case ValueArrayTypeIntegerDistribution: var val ValueArrayIntegerDistribution - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Values = val case ValueArrayTypeDoubleDistribution: var val ValueArrayDoubleDistribution - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Values = val @@ -7794,6 +7736,7 @@ type VpcFirewallRuleHostFilter struct { func (v *VpcFirewallRuleHostFilter) UnmarshalJSON(data []byte) error { var peek struct { Discriminator VpcFirewallRuleHostFilterType `json:"type"` + Value json.RawMessage `json:"value"` } if err := json.Unmarshal(data, &peek); err != nil { return err @@ -7801,31 +7744,31 @@ func (v *VpcFirewallRuleHostFilter) UnmarshalJSON(data []byte) error { switch peek.Discriminator { case VpcFirewallRuleHostFilterTypeVpc: var val VpcFirewallRuleHostFilterVpc - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleHostFilterTypeSubnet: var val VpcFirewallRuleHostFilterSubnet - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleHostFilterTypeInstance: var val VpcFirewallRuleHostFilterInstance - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleHostFilterTypeIp: var val VpcFirewallRuleHostFilterIp - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleHostFilterTypeIpNet: var val VpcFirewallRuleHostFilterIpNet - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val @@ -7937,6 +7880,7 @@ type VpcFirewallRuleTarget struct { func (v *VpcFirewallRuleTarget) UnmarshalJSON(data []byte) error { var peek struct { Discriminator VpcFirewallRuleTargetType `json:"type"` + Value json.RawMessage `json:"value"` } if err := json.Unmarshal(data, &peek); err != nil { return err @@ -7944,31 +7888,31 @@ func (v *VpcFirewallRuleTarget) UnmarshalJSON(data []byte) error { switch peek.Discriminator { case VpcFirewallRuleTargetTypeVpc: var val VpcFirewallRuleTargetVpc - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleTargetTypeSubnet: var val VpcFirewallRuleTargetSubnet - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleTargetTypeInstance: var val VpcFirewallRuleTargetInstance - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleTargetTypeIp: var val VpcFirewallRuleTargetIp - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val case VpcFirewallRuleTargetTypeIpNet: var val VpcFirewallRuleTargetIpNet - if err := json.Unmarshal(data, &val); err != nil { + if err := json.Unmarshal(peek.Value, &val); err != nil { return err } v.Value = val