diff --git a/gen/schema_gen.go b/gen/schema_gen.go index 263164eb5..0e8832e86 100644 --- a/gen/schema_gen.go +++ b/gen/schema_gen.go @@ -252,6 +252,18 @@ func (g *schemaGen) generate2(name string, schema *jsonschema.Schema) (ret *ir.T return nil, err } oneOf = t + case len(schema.Enum) > 0: + switch schema.Type { + case jsonschema.String, + jsonschema.Integer, + jsonschema.Number, + jsonschema.Boolean, + jsonschema.Null: + default: + return nil, &ErrNotImplemented{ + Name: fmt.Sprintf("non-primitive enum"), + } + } } switch schema.Type { diff --git a/gen/schema_gen_primitive.go b/gen/schema_gen_primitive.go index 909893bfb..961140cd3 100644 --- a/gen/schema_gen_primitive.go +++ b/gen/schema_gen_primitive.go @@ -9,6 +9,7 @@ import ( "github.com/ogen-go/ogen/gen/ir" "github.com/ogen-go/ogen/jsonschema" + "github.com/ogen-go/ogen/location" ) func (g *schemaGen) primitive(name string, schema *jsonschema.Schema) (*ir.Type, error) { @@ -28,6 +29,9 @@ func (g *schemaGen) enum(name string, t *ir.Type, schema *jsonschema.Schema) (*i if f := schema.Format; f != "" && !t.IsNumeric() { return nil, errors.Wrapf(&ErrNotImplemented{"enum format"}, "format %q", f) } + if err := g.validateEnumValues(schema); err != nil { + return nil, errors.Wrap(err, "validate enum") + } type namingStrategy int const ( @@ -146,6 +150,64 @@ func (g *schemaGen) enum(name string, t *ir.Type, schema *jsonschema.Schema) (*i }, nil } +func (g *schemaGen) validateEnumValues(s *jsonschema.Schema) error { + reportErr := func(idx int, err error) error { + pos, ok := s.Pointer.Field("enum").Index(idx).Position() + if !ok { + return err + } + return &location.Error{ + File: s.Pointer.File(), + Pos: pos, + Err: err, + } + } + + switch typ := s.Type; typ { + case jsonschema.Object, jsonschema.Array, jsonschema.Empty: + return &ErrNotImplemented{Name: "non-primitive enum"} + case jsonschema.Integer: + for idx, val := range s.Enum { + if _, ok := val.(int64); !ok { + return reportErr(idx, errors.Errorf("enum value should be an integer, got %T", val)) + } + } + return nil + case jsonschema.Number: + for idx, val := range s.Enum { + switch val.(type) { + case int64, float64: + default: + return reportErr(idx, errors.Errorf("enum value should be a number, got %T", val)) + } + } + return nil + case jsonschema.String: + for idx, val := range s.Enum { + if _, ok := val.(string); !ok { + return reportErr(idx, errors.Errorf("enum value should be a string, got %T", val)) + } + } + return nil + case jsonschema.Boolean: + for idx, val := range s.Enum { + if _, ok := val.(bool); !ok { + return reportErr(idx, errors.Errorf("enum value should be a boolean, got %T", val)) + } + } + return nil + case jsonschema.Null: + for idx, val := range s.Enum { + if val != nil { + return reportErr(idx, errors.Errorf("enum value should be a null, got %T", val)) + } + } + return nil + default: + panic(fmt.Sprintf("unexpected schema type %q", typ)) + } +} + func (g *schemaGen) parseSimple(schema *jsonschema.Schema) *ir.Type { mapping := TypeFormatMapping()