go: vendor the oapi-codegen cmd

See the comment in tools.go, I cannot fully explain what's happening here.
Somehow, Go 1.14 wants to use the vendored version of oapi-codegen but
without this file, oapi-codegen isn't vendored so the generation fails.

Signed-off-by: Ondřej Budai <ondrej@budai.cz>
This commit is contained in:
Ondřej Budai 2021-01-29 09:56:22 +01:00 committed by Ondřej Budai
parent 1a3cbb282a
commit 2241a8d9ed
75 changed files with 11211 additions and 0 deletions

2
vendor/github.com/getkin/kin-openapi/jsoninfo/doc.go generated vendored Normal file
View file

@ -0,0 +1,2 @@
// Package jsoninfo provides information and functions for marshalling/unmarshalling JSON.
package jsoninfo

View file

@ -0,0 +1,122 @@
package jsoninfo
import (
"reflect"
"strings"
"unicode"
"unicode/utf8"
)
// FieldInfo contains information about JSON serialization of a field.
type FieldInfo struct {
MultipleFields bool // Whether multiple Go fields share this JSON name
HasJSONTag bool
TypeIsMarshaller bool
TypeIsUnmarshaller bool
JSONOmitEmpty bool
JSONString bool
Index []int
Type reflect.Type
JSONName string
}
func AppendFields(fields []FieldInfo, parentIndex []int, t reflect.Type) []FieldInfo {
// For each field
numField := t.NumField()
iteration:
for i := 0; i < numField; i++ {
f := t.Field(i)
index := make([]int, 0, len(parentIndex)+1)
index = append(index, parentIndex...)
index = append(index, i)
// See whether this is an embedded field
if f.Anonymous {
if f.Tag.Get("json") == "-" {
continue
}
fields = AppendFields(fields, index, f.Type)
continue iteration
}
// Ignore certain types
switch f.Type.Kind() {
case reflect.Func, reflect.Chan:
continue iteration
}
// Is it a private (lowercase) field?
firstRune, _ := utf8.DecodeRuneInString(f.Name)
if unicode.IsLower(firstRune) {
continue iteration
}
// Declare a field
field := FieldInfo{
Index: index,
Type: f.Type,
JSONName: f.Name,
}
// Read "json" tag
jsonTag := f.Tag.Get("json")
// Read our custom "multijson" tag that
// allows multiple fields with the same name.
if v := f.Tag.Get("multijson"); len(v) > 0 {
field.MultipleFields = true
jsonTag = v
}
// Handle "-"
if jsonTag == "-" {
continue
}
// Parse the tag
if len(jsonTag) > 0 {
field.HasJSONTag = true
for i, part := range strings.Split(jsonTag, ",") {
if i == 0 {
if len(part) > 0 {
field.JSONName = part
}
} else {
switch part {
case "omitempty":
field.JSONOmitEmpty = true
case "string":
field.JSONString = true
}
}
}
}
if _, ok := field.Type.MethodByName("MarshalJSON"); ok {
field.TypeIsMarshaller = true
}
if _, ok := field.Type.MethodByName("UnmarshalJSON"); ok {
field.TypeIsUnmarshaller = true
}
// Field is done
fields = append(fields, field)
}
return fields
}
type sortableFieldInfos []FieldInfo
func (list sortableFieldInfos) Len() int {
return len(list)
}
func (list sortableFieldInfos) Less(i, j int) bool {
return list[i].JSONName < list[j].JSONName
}
func (list sortableFieldInfos) Swap(i, j int) {
a, b := list[i], list[j]
list[i], list[j] = b, a
}

View file

@ -0,0 +1,162 @@
package jsoninfo
import (
"encoding/json"
"fmt"
"reflect"
)
// MarshalStrictStruct function:
// * Marshals struct fields, ignoring MarshalJSON() and fields without 'json' tag.
// * Correctly handles StrictStruct semantics.
func MarshalStrictStruct(value StrictStruct) ([]byte, error) {
encoder := NewObjectEncoder()
if err := value.EncodeWith(encoder, value); err != nil {
return nil, err
}
return encoder.Bytes()
}
type ObjectEncoder struct {
result map[string]json.RawMessage
}
func NewObjectEncoder() *ObjectEncoder {
return &ObjectEncoder{
result: make(map[string]json.RawMessage, 8),
}
}
// Bytes returns the result of encoding.
func (encoder *ObjectEncoder) Bytes() ([]byte, error) {
return json.Marshal(encoder.result)
}
// EncodeExtension adds a key/value to the current JSON object.
func (encoder *ObjectEncoder) EncodeExtension(key string, value interface{}) error {
data, err := json.Marshal(value)
if err != nil {
return err
}
encoder.result[key] = data
return nil
}
// EncodeExtensionMap adds all properties to the result.
func (encoder *ObjectEncoder) EncodeExtensionMap(value map[string]json.RawMessage) error {
if value != nil {
result := encoder.result
for k, v := range value {
result[k] = v
}
}
return nil
}
func (encoder *ObjectEncoder) EncodeStructFieldsAndExtensions(value interface{}) error {
reflection := reflect.ValueOf(value)
// Follow "encoding/json" semantics
if reflection.Kind() != reflect.Ptr {
// Panic because this is a clear programming error
panic(fmt.Errorf("Value %s is not a pointer", reflection.Type().String()))
}
if reflection.IsNil() {
// Panic because this is a clear programming error
panic(fmt.Errorf("Value %s is nil", reflection.Type().String()))
}
// Take the element
reflection = reflection.Elem()
// Obtain typeInfo
typeInfo := GetTypeInfo(reflection.Type())
// Declare result
result := encoder.result
// Supported fields
iteration:
for _, field := range typeInfo.Fields {
// Fields without JSON tag are ignored
if !field.HasJSONTag {
continue
}
// Marshal
fieldValue := reflection.FieldByIndex(field.Index)
if v, ok := fieldValue.Interface().(json.Marshaler); ok {
if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
if field.JSONOmitEmpty {
continue iteration
}
result[field.JSONName] = []byte("null")
continue
}
fieldData, err := v.MarshalJSON()
if err != nil {
return err
}
result[field.JSONName] = fieldData
continue
}
switch fieldValue.Kind() {
case reflect.Ptr, reflect.Interface:
if fieldValue.IsNil() {
if field.JSONOmitEmpty {
continue iteration
}
result[field.JSONName] = []byte("null")
continue
}
case reflect.Struct:
case reflect.Map:
if field.JSONOmitEmpty && (fieldValue.IsNil() || fieldValue.Len() == 0) {
continue iteration
}
case reflect.Slice:
if field.JSONOmitEmpty && fieldValue.Len() == 0 {
continue iteration
}
case reflect.Bool:
x := fieldValue.Bool()
if field.JSONOmitEmpty && !x {
continue iteration
}
s := "false"
if x {
s = "true"
}
result[field.JSONName] = []byte(s)
continue iteration
case reflect.Int64, reflect.Int, reflect.Int32:
if field.JSONOmitEmpty && fieldValue.Int() == 0 {
continue iteration
}
case reflect.Uint64, reflect.Uint, reflect.Uint32:
if field.JSONOmitEmpty && fieldValue.Uint() == 0 {
continue iteration
}
case reflect.Float64:
if field.JSONOmitEmpty && fieldValue.Float() == 0.0 {
continue iteration
}
case reflect.String:
if field.JSONOmitEmpty && len(fieldValue.String()) == 0 {
continue iteration
}
default:
panic(fmt.Errorf("Field '%s' has unsupported type %s", field.JSONName, field.Type.String()))
}
// No special treament is needed
// Use plain old "encoding/json".Marshal
fieldData, err := json.Marshal(fieldValue.Addr().Interface())
if err != nil {
return err
}
result[field.JSONName] = fieldData
}
return nil
}

View file

@ -0,0 +1,30 @@
package jsoninfo
import (
"encoding/json"
)
func MarshalRef(value string, otherwise interface{}) ([]byte, error) {
if len(value) > 0 {
return json.Marshal(&refProps{
Ref: value,
})
}
return json.Marshal(otherwise)
}
func UnmarshalRef(data []byte, destRef *string, destOtherwise interface{}) error {
refProps := &refProps{}
if err := json.Unmarshal(data, refProps); err == nil {
ref := refProps.Ref
if len(ref) > 0 {
*destRef = ref
return nil
}
}
return json.Unmarshal(data, destOtherwise)
}
type refProps struct {
Ref string `json:"$ref,omitempty"`
}

View file

@ -0,0 +1,6 @@
package jsoninfo
type StrictStruct interface {
EncodeWith(encoder *ObjectEncoder, value interface{}) error
DecodeWith(decoder *ObjectDecoder, value interface{}) error
}

View file

@ -0,0 +1,68 @@
package jsoninfo
import (
"reflect"
"sort"
"sync"
)
var (
typeInfos = map[reflect.Type]*TypeInfo{}
typeInfosMutex sync.RWMutex
)
// TypeInfo contains information about JSON serialization of a type
type TypeInfo struct {
Type reflect.Type
Fields []FieldInfo
}
func GetTypeInfoForValue(value interface{}) *TypeInfo {
return GetTypeInfo(reflect.TypeOf(value))
}
// GetTypeInfo returns TypeInfo for the given type.
func GetTypeInfo(t reflect.Type) *TypeInfo {
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
typeInfosMutex.RLock()
typeInfo, exists := typeInfos[t]
typeInfosMutex.RUnlock()
if exists {
return typeInfo
}
if t.Kind() != reflect.Struct {
typeInfo = &TypeInfo{
Type: t,
}
} else {
// Allocate
typeInfo = &TypeInfo{
Type: t,
Fields: make([]FieldInfo, 0, 16),
}
// Add fields
typeInfo.Fields = AppendFields(nil, nil, t)
// Sort fields
sort.Sort(sortableFieldInfos(typeInfo.Fields))
}
// Publish
typeInfosMutex.Lock()
typeInfos[t] = typeInfo
typeInfosMutex.Unlock()
return typeInfo
}
// FieldNames returns all field names
func (typeInfo *TypeInfo) FieldNames() []string {
fields := typeInfo.Fields
names := make([]string, 0, len(fields))
for _, field := range fields {
names = append(names, field.JSONName)
}
return names
}

View file

@ -0,0 +1,121 @@
package jsoninfo
import (
"encoding/json"
"fmt"
"reflect"
)
// UnmarshalStrictStruct function:
// * Unmarshals struct fields, ignoring UnmarshalJSON(...) and fields without 'json' tag.
// * Correctly handles StrictStruct
func UnmarshalStrictStruct(data []byte, value StrictStruct) error {
decoder, err := NewObjectDecoder(data)
if err != nil {
return err
}
return value.DecodeWith(decoder, value)
}
type ObjectDecoder struct {
Data []byte
remainingFields map[string]json.RawMessage
}
func NewObjectDecoder(data []byte) (*ObjectDecoder, error) {
var remainingFields map[string]json.RawMessage
if err := json.Unmarshal(data, &remainingFields); err != nil {
return nil, fmt.Errorf("Failed to unmarshal extension properties: %v\nInput: %s", err, data)
}
return &ObjectDecoder{
Data: data,
remainingFields: remainingFields,
}, nil
}
// DecodeExtensionMap returns all properties that were not decoded previously.
func (decoder *ObjectDecoder) DecodeExtensionMap() map[string]json.RawMessage {
return decoder.remainingFields
}
func (decoder *ObjectDecoder) DecodeStructFieldsAndExtensions(value interface{}) error {
reflection := reflect.ValueOf(value)
if reflection.Kind() != reflect.Ptr {
panic(fmt.Errorf("Value %T is not a pointer", value))
}
if reflection.IsNil() {
panic(fmt.Errorf("Value %T is nil", value))
}
reflection = reflection.Elem()
for (reflection.Kind() == reflect.Interface || reflection.Kind() == reflect.Ptr) && !reflection.IsNil() {
reflection = reflection.Elem()
}
reflectionType := reflection.Type()
if reflectionType.Kind() != reflect.Struct {
panic(fmt.Errorf("Value %T is not a struct", value))
}
typeInfo := GetTypeInfo(reflectionType)
// Supported fields
fields := typeInfo.Fields
remainingFields := decoder.remainingFields
for fieldIndex, field := range fields {
// Fields without JSON tag are ignored
if !field.HasJSONTag {
continue
}
// Get data
fieldData, exists := remainingFields[field.JSONName]
if !exists {
continue
}
// Unmarshal
if field.TypeIsUnmarshaller {
fieldType := field.Type
isPtr := false
if fieldType.Kind() == reflect.Ptr {
fieldType = fieldType.Elem()
isPtr = true
}
fieldValue := reflect.New(fieldType)
if err := fieldValue.Interface().(json.Unmarshaler).UnmarshalJSON(fieldData); err != nil {
if field.MultipleFields {
i := fieldIndex + 1
if i < len(fields) && fields[i].JSONName == field.JSONName {
continue
}
}
return fmt.Errorf("Error while unmarshalling property '%s' (%s): %v",
field.JSONName, fieldValue.Type().String(), err)
}
if !isPtr {
fieldValue = fieldValue.Elem()
}
reflection.FieldByIndex(field.Index).Set(fieldValue)
// Remove the field from remaining fields
delete(remainingFields, field.JSONName)
} else {
fieldPtr := reflection.FieldByIndex(field.Index)
if fieldPtr.Kind() != reflect.Ptr || fieldPtr.IsNil() {
fieldPtr = fieldPtr.Addr()
}
if err := json.Unmarshal(fieldData, fieldPtr.Interface()); err != nil {
if field.MultipleFields {
i := fieldIndex + 1
if i < len(fields) && fields[i].JSONName == field.JSONName {
continue
}
}
return fmt.Errorf("Error while unmarshalling property '%s' (%s): %v",
field.JSONName, fieldPtr.Type().String(), err)
}
// Remove the field from remaining fields
delete(remainingFields, field.JSONName)
}
}
return nil
}

View file

@ -0,0 +1,45 @@
package jsoninfo
import (
"encoding/json"
"fmt"
"sort"
"strings"
)
// UnsupportedPropertiesError is a helper for extensions that want to refuse
// unsupported JSON object properties.
//
// It produces a helpful error message.
type UnsupportedPropertiesError struct {
Value interface{}
UnsupportedProperties map[string]json.RawMessage
}
func NewUnsupportedPropertiesError(v interface{}, m map[string]json.RawMessage) error {
return &UnsupportedPropertiesError{
Value: v,
UnsupportedProperties: m,
}
}
func (err *UnsupportedPropertiesError) Error() string {
m := err.UnsupportedProperties
typeInfo := GetTypeInfoForValue(err.Value)
if m == nil || typeInfo == nil {
return "Invalid UnsupportedPropertiesError"
}
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
supported := typeInfo.FieldNames()
if len(supported) == 0 {
return fmt.Sprintf("Type '%T' doesn't take any properties. Unsupported properties: '%s'\n",
err.Value, strings.Join(keys, "', '"))
}
return fmt.Sprintf("Unsupported properties: '%s'\nSupported properties are: '%s'",
strings.Join(keys, "', '"),
strings.Join(supported, "', '"))
}