mirror of https://github.com/go-gitea/gitea.git
120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
![]() |
// Copyright (C) MongoDB, Inc. 2017-present.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||
|
// not use this file except in compliance with the License. You may obtain
|
||
|
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
package bsoncodec
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// StructTagParser returns the struct tags for a given struct field.
|
||
|
type StructTagParser interface {
|
||
|
ParseStructTags(reflect.StructField) (StructTags, error)
|
||
|
}
|
||
|
|
||
|
// StructTagParserFunc is an adapter that allows a generic function to be used
|
||
|
// as a StructTagParser.
|
||
|
type StructTagParserFunc func(reflect.StructField) (StructTags, error)
|
||
|
|
||
|
// ParseStructTags implements the StructTagParser interface.
|
||
|
func (stpf StructTagParserFunc) ParseStructTags(sf reflect.StructField) (StructTags, error) {
|
||
|
return stpf(sf)
|
||
|
}
|
||
|
|
||
|
// StructTags represents the struct tag fields that the StructCodec uses during
|
||
|
// the encoding and decoding process.
|
||
|
//
|
||
|
// In the case of a struct, the lowercased field name is used as the key for each exported
|
||
|
// field but this behavior may be changed using a struct tag. The tag may also contain flags to
|
||
|
// adjust the marshalling behavior for the field.
|
||
|
//
|
||
|
// The properties are defined below:
|
||
|
//
|
||
|
// OmitEmpty Only include the field if it's not set to the zero value for the type or to
|
||
|
// empty slices or maps.
|
||
|
//
|
||
|
// MinSize Marshal an integer of a type larger than 32 bits value as an int32, if that's
|
||
|
// feasible while preserving the numeric value.
|
||
|
//
|
||
|
// Truncate When unmarshaling a BSON double, it is permitted to lose precision to fit within
|
||
|
// a float32.
|
||
|
//
|
||
|
// Inline Inline the field, which must be a struct or a map, causing all of its fields
|
||
|
// or keys to be processed as if they were part of the outer struct. For maps,
|
||
|
// keys must not conflict with the bson keys of other struct fields.
|
||
|
//
|
||
|
// Skip This struct field should be skipped. This is usually denoted by parsing a "-"
|
||
|
// for the name.
|
||
|
//
|
||
|
// TODO(skriptble): Add tags for undefined as nil and for null as nil.
|
||
|
type StructTags struct {
|
||
|
Name string
|
||
|
OmitEmpty bool
|
||
|
MinSize bool
|
||
|
Truncate bool
|
||
|
Inline bool
|
||
|
Skip bool
|
||
|
}
|
||
|
|
||
|
// DefaultStructTagParser is the StructTagParser used by the StructCodec by default.
|
||
|
// It will handle the bson struct tag. See the documentation for StructTags to see
|
||
|
// what each of the returned fields means.
|
||
|
//
|
||
|
// If there is no name in the struct tag fields, the struct field name is lowercased.
|
||
|
// The tag formats accepted are:
|
||
|
//
|
||
|
// "[<key>][,<flag1>[,<flag2>]]"
|
||
|
//
|
||
|
// `(...) bson:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||
|
//
|
||
|
// An example:
|
||
|
//
|
||
|
// type T struct {
|
||
|
// A bool
|
||
|
// B int "myb"
|
||
|
// C string "myc,omitempty"
|
||
|
// D string `bson:",omitempty" json:"jsonkey"`
|
||
|
// E int64 ",minsize"
|
||
|
// F int64 "myf,omitempty,minsize"
|
||
|
// }
|
||
|
//
|
||
|
// A struct tag either consisting entirely of '-' or with a bson key with a
|
||
|
// value consisting entirely of '-' will return a StructTags with Skip true and
|
||
|
// the remaining fields will be their default values.
|
||
|
var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) {
|
||
|
key := strings.ToLower(sf.Name)
|
||
|
tag, ok := sf.Tag.Lookup("bson")
|
||
|
if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 {
|
||
|
tag = string(sf.Tag)
|
||
|
}
|
||
|
var st StructTags
|
||
|
if tag == "-" {
|
||
|
st.Skip = true
|
||
|
return st, nil
|
||
|
}
|
||
|
|
||
|
for idx, str := range strings.Split(tag, ",") {
|
||
|
if idx == 0 && str != "" {
|
||
|
key = str
|
||
|
}
|
||
|
switch str {
|
||
|
case "omitempty":
|
||
|
st.OmitEmpty = true
|
||
|
case "minsize":
|
||
|
st.MinSize = true
|
||
|
case "truncate":
|
||
|
st.Truncate = true
|
||
|
case "inline":
|
||
|
st.Inline = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
st.Name = key
|
||
|
|
||
|
return st, nil
|
||
|
}
|