mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 04:20:11 +00:00
Also ran `gofmt` across the entire project. Things need cleaning up. Signed-off-by: Dave Shanley <dave@quobix.com>
101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package base
|
|
|
|
import (
|
|
"github.com/pb33f/libopenapi/datamodel/high"
|
|
"gopkg.in/yaml.v3"
|
|
"reflect"
|
|
)
|
|
|
|
// DynamicValue is used to hold multiple possible values for a schema property. There are two values, a left
|
|
// value (A) and a right value (B). The left value (A) is a 3.0 schema property value, the right value (B) is a 3.1
|
|
// schema value.
|
|
//
|
|
// OpenAPI 3.1 treats a Schema as a real JSON schema, which means some properties become incompatible, or others
|
|
// now support more than one primitive type or structure.
|
|
// The N value is a bit to make it each to know which value (A or B) is used, this prevents having to
|
|
// if/else on the value to determine which one is set.
|
|
type DynamicValue[A any, B any] struct {
|
|
N int // 0 == A, 1 == B
|
|
A A
|
|
B B
|
|
inline bool
|
|
}
|
|
|
|
// IsA will return true if the 'A' or left value is set. (OpenAPI 3)
|
|
func (d *DynamicValue[A, B]) IsA() bool {
|
|
return d.N == 0
|
|
}
|
|
|
|
// IsB will return true if the 'B' or right value is set (OpenAPI 3.1)
|
|
func (d *DynamicValue[A, B]) IsB() bool {
|
|
return d.N == 1
|
|
}
|
|
|
|
func (d *DynamicValue[A, B]) Render() ([]byte, error) {
|
|
d.inline = false
|
|
return yaml.Marshal(d)
|
|
}
|
|
|
|
func (d *DynamicValue[A, B]) RenderInline() ([]byte, error) {
|
|
d.inline = true
|
|
return yaml.Marshal(d)
|
|
}
|
|
|
|
// MarshalYAML will create a ready to render YAML representation of the DynamicValue object.
|
|
func (d *DynamicValue[A, B]) MarshalYAML() (interface{}, error) {
|
|
// this is a custom renderer, we can't use the NodeBuilder out of the gate.
|
|
var n yaml.Node
|
|
var err error
|
|
var value any
|
|
|
|
if d.IsA() {
|
|
value = d.A
|
|
}
|
|
if d.IsB() {
|
|
value = d.B
|
|
}
|
|
to := reflect.TypeOf(value)
|
|
switch to.Kind() {
|
|
case reflect.Ptr:
|
|
if d.inline {
|
|
if r, ok := value.(high.RenderableInline); ok {
|
|
return r.MarshalYAMLInline()
|
|
} else {
|
|
_ = n.Encode(value)
|
|
}
|
|
} else {
|
|
if r, ok := value.(high.Renderable); ok {
|
|
return r.MarshalYAML()
|
|
} else {
|
|
_ = n.Encode(value)
|
|
}
|
|
}
|
|
case reflect.Bool:
|
|
_ = n.Encode(value.(bool))
|
|
case reflect.Int:
|
|
_ = n.Encode(value.(int))
|
|
case reflect.String:
|
|
_ = n.Encode(value.(string))
|
|
case reflect.Int64:
|
|
_ = n.Encode(value.(int64))
|
|
case reflect.Float64:
|
|
_ = n.Encode(value.(float64))
|
|
case reflect.Float32:
|
|
_ = n.Encode(value.(float32))
|
|
case reflect.Int32:
|
|
_ = n.Encode(value.(int32))
|
|
|
|
}
|
|
return &n, err
|
|
}
|
|
|
|
// MarshalYAMLInline will create a ready to render YAML representation of the DynamicValue object. The
|
|
// references will be inlined instead of kept as references.
|
|
func (d *DynamicValue[A, B]) MarshalYAMLInline() (interface{}, error) {
|
|
d.inline = true
|
|
return d.MarshalYAML()
|
|
}
|