Documentation
¶
Overview ¶
Package rs provides rendering suffix support for yaml
Index ¶
- Constants
- func InitRecursively(fv reflect.Value, opts *Options)
- func InitRecursivelyLimitDepth(fv reflect.Value, depth int, opts *Options)
- func InitReflectValue(in reflect.Value, opts *Options) bool
- func MergeMap(original, additional map[string]any, appendList bool, uniqueInListItems bool) (map[string]any, error)
- func NormalizeRawData(rawData any) (any, error)
- func UniqueList(dt []any) []any
- type AnyObject
- func (o *AnyObject) MarshalJSON() ([]byte, error)
- func (o *AnyObject) MarshalYAML() (any, error)
- func (o *AnyObject) NormalizedValue() any
- func (o *AnyObject) ResolveFields(rc RenderingHandler, depth int, names ...string) error
- func (o *AnyObject) UnmarshalJSON(p []byte) error
- func (o *AnyObject) UnmarshalYAML(n *yaml.Node) error
- type AnyObjectMap
- type BaseField
- type Field
- type InterfaceTypeHandleFunc
- type InterfaceTypeHandler
- type JSONPatchSpec
- type MergeSource
- type Options
- type PatchSpec
- type RenderingHandleFunc
- type RenderingHandler
- type TypeHint
- type TypeHintBool
- type TypeHintFloat
- type TypeHintInt
- type TypeHintNone
- type TypeHintObject
- type TypeHintObjects
- type TypeHintStr
Examples ¶
Constants ¶
const ( TagNameRS = "rs" TagName = TagNameRS )
Struct field tag names used by this package
const ( // ErrInterfaceTypeNotHandled is expected to be throwed by Options.InterfaceTypeHandler // when the requested interface type was not handled // // it is only considered as an error when the target interface type is not `any` (interface{}), // or in other words, // it is not considered an error when InterfaceTypeHandler returned this error with `interface{}` type // as expected typed ErrInterfaceTypeNotHandled = errString("interface type not handled") )
Variables ¶
This section is empty.
Functions ¶
func InitRecursively ¶
InitRecursively is InitRecursivelyLimitDepth with depth = -1
func InitRecursivelyLimitDepth ¶ added in v0.11.0
InitRecursivelyLimitDepth
func InitReflectValue ¶ added in v0.10.0
InitReflectValue returns true when BaseField of `in` is initilized after the call
func MergeMap ¶
func NormalizeRawData ¶ added in v0.5.1
NormalizeRawData decodes the rawData to common go value (nil, string, integers ...) if the type of rawData is *yaml.Node
Types ¶
type AnyObject ¶
type AnyObject struct { BaseField `yaml:"-" json:"-"` // contains filtered or unexported fields }
AnyObject is a `any` equivalent with rendering suffix support
func (*AnyObject) NormalizedValue ¶ added in v0.3.0
NormalizedValue returns underlying value of the AnyObject with primitive types that is:
* for maps: map[string]any * for slices: []any * and primitive types for scalar types
should be called after fields being resolved
func (*AnyObject) ResolveFields ¶
func (o *AnyObject) ResolveFields(rc RenderingHandler, depth int, names ...string) error
func (*AnyObject) UnmarshalJSON ¶ added in v0.10.0
type AnyObjectMap ¶ added in v0.3.0
AnyObjectMap is a `map[string]any` equivalent with rendering suffix support
func (*AnyObjectMap) MarshalJSON ¶ added in v0.3.0
func (aom *AnyObjectMap) MarshalJSON() ([]byte, error)
func (*AnyObjectMap) MarshalYAML ¶ added in v0.3.0
func (aom *AnyObjectMap) MarshalYAML() (any, error)
func (*AnyObjectMap) NormalizedValue ¶ added in v0.3.0
func (aom *AnyObjectMap) NormalizedValue() map[string]any
NormalizedValue returns value of the AnyObjectMap with type map[string]any
func (*AnyObjectMap) UnmarshalJSON ¶ added in v0.10.0
func (aom *AnyObjectMap) UnmarshalJSON(p []byte) error
type BaseField ¶
type BaseField struct {
// contains filtered or unexported fields
}
BaseField is a helper struct type implementing Field interface it serves as a cache storage for encoding/decoding
func (*BaseField) Inherit ¶
Inherit unresolved fields from another BaseField useful when you are merging two structs and want to resolve only once to get all unresolved fields set
after a successful function call, f wiil be able to resolve its struct fields with unresolved values from b and its own
func (*BaseField) MarshalYAML ¶ added in v0.4.0
MarshalYAML implements yaml.Marshaler by making a map of all fields known to BaseField
You can opt-out with build tag `rs_noyamlmarshaler`
func (*BaseField) ResolveFields ¶
func (f *BaseField) ResolveFields(rc RenderingHandler, depth int, names ...string) (err error)
Example ¶
type MyStruct struct { rs.BaseField `yaml:"-"` MyValue string `yaml:"my_value"` } // required: // initialize you data object // before marshaling/unmarshaling/resolving s := rs.Init(&MyStruct{}, nil).(*MyStruct) // unmarshal yaml data using rendering suffix err := yaml.Unmarshal([]byte(`{ my_value@my-renderer: 123 }`), s) if err != nil { panic(err) } err = s.ResolveFields( // implement your own renderer rs.RenderingHandleFunc( func(renderer string, rawData any) (result []byte, err error) { // usually you should have rawData normalized as golang types // so you don't have to tend to low level *yaml.Node objects rawData, err = rs.NormalizeRawData(rawData) if err != nil { return nil, err } switch vt := rawData.(type) { case string: return []byte(vt), nil case []byte: return vt, nil default: return []byte("hello"), nil } }, ), -1, ) if err != nil { panic(err) } fmt.Println(s.MyValue)
Output: hello
type Field ¶
type Field interface { // A Field must implement yaml.Unmarshaler interface to process rendering suffix // in yaml key yaml.Unmarshaler // ResolveFields sets struct field values with data from unmarshaled yaml // // depth controls to what level this function call goes // when depth >= 1, resolve inner fields until reaching depth limit (depth == 0) // when depth == 0, do nothing // when depth < 0, resolve recursively // // names limits which fields to be resolved, their values are derived from // your field tags // When it's not empty, resolve specified fields only, otherwise, resolve all exported fields // in the struct. ResolveFields(rc RenderingHandler, depth int, names ...string) error }
Field defines methods required for rendering suffix support
these methods are implemented by BaseField, so usually you should just embed BaseField in your struct as the very first field
func Init ¶
Init the BaseField embedded in your struct, the BaseField must be the first field
type Foo struct { rs.BaseField // or *rs.BaseField }
NOTE: if the arg `in` doesn't contain BaseField or the BaseField is not the first element it does nothing and will return `in` as is.
type InterfaceTypeHandleFunc ¶
InterfaceTypeHandleFunc is a helper type to wrap your function as InterfaceTypeHandler
type InterfaceTypeHandler ¶
type InterfaceTypeHandler interface { // Create request interface type using yaml information Create(typ reflect.Type, yamlKey string) (any, error) }
InterfaceTypeHandler is used when setting values for any typed field
type JSONPatchSpec ¶
type JSONPatchSpec struct { BaseField `yaml:"-" json:"-"` Operation string `yaml:"op"` Path string `yaml:"path"` Value *yaml.Node `yaml:"value,omitempty"` // Resolve rendering suffix in value before being applied // // Defaults to `true` Resolve *bool `yaml:"resolve"` // Select part of the value for patching // // this action happens before patching Select string `yaml:"select"` }
JSONPatchSpec per rfc6902
type MergeSource ¶
type MergeSource struct { BaseField `yaml:"-" json:"-"` // Value for the source Value *yaml.Node `yaml:"value,omitempty"` // Resolve rendering suffix in value if any before being merged // // Defaults to `true` Resolve *bool `yaml:"resolve"` // Select some data from the source Select string `yaml:"select,omitempty"` }
type Options ¶ added in v0.4.0
type Options struct { // InterfaceTypeHandler handles interface value creation for any field // with a interface{...} type (including []interface{...} and map[string]interface{...}) // // for example, define a interface type Foo: // type Foo interface{ Bar() string } // // with InterfaceTypeHandler you can return values whose type impelemts Foo during unmarshaling // // defaults to `nil` InterfaceTypeHandler InterfaceTypeHandler // DataTagNamespace used for struct field tag parsing // you can set it to json to use json tag // // supported tag values are: // - <first tag value as data field name> // - inline // - omitempty // // unsupported tag values are ignored // // defaults to `yaml` DataTagNamespace string // AllowUnknownFields whether restrict unmarshaling to known fields // // NOTE: if there is a map field in struct with tag `rs:"inline"` // even when AllowUnknownFields is set to false, it still gets these unknown // fields marshaled to that map field // // defaults to `false` AllowUnknownFields bool // AllowedRenderers limit renderers can be applied in rendering suffix // when this option is not set (nil), not renderer will be rejected // when set, only renderers with exact name matching will be allowed, // thus you may need to set an empty entry to allow pseudo built-in // empty renderer AllowedRenderers map[string]struct{} }
type PatchSpec ¶
type PatchSpec struct { BaseField `yaml:"-" json:"-"` // Value for the renderer // // say we have a yaml list (`[bar]`) stored at https://example.com/bar.yaml // // foo@http!: // value: https://example.com/bar.yaml // merge: { value: [foo] } // // then the resolved value of foo will be `[bar, foo]` Value *yaml.Node `yaml:"value"` // Resolve rendering suffix in value if any before being patched // // Defaults to `true` Resolve *bool `yaml:"resolve"` // Merge additional data into Value // // this action happens first Merge []MergeSource `yaml:"merge,omitempty"` // Patch Value using standard rfc6902 json-patch // // this action happens after merge Patch []JSONPatchSpec `yaml:"patch"` // Select part of the data as final result // // this action happens after merge and patch // TODO: support jq variables Select string `yaml:"select"` // Unique to make sure elements in the sequence is unique // // only effective when Value is yaml sequence Unique bool `yaml:"unique"` // MapListItemUnique to ensure items are unique in all merged lists respectively // lists with no merge data input are untouched MapListItemUnique bool `yaml:"map_list_item_unique"` // MapListAppend to append lists instead of replacing existing list MapListAppend bool `yaml:"map_list_append"` }
PatchSpec is the input definition for renderers with a patching suffix
func (*PatchSpec) Apply ¶ added in v0.8.0
func (s *PatchSpec) Apply(rc RenderingHandler) (_ any, err error)
Apply Merge and Patch to Value, Unique is ensured if set to true
type RenderingHandleFunc ¶ added in v0.4.0
RenderingHandleFunc is a helper type to wrap your function as RenderingHandler
type RenderingHandler ¶
type RenderingHandler interface { // RenderYaml transforms rawData to result through the renderer // // renderer is the name of your renderer without type hint (`?<hint>`) and patch suffix (`!`) // // rawData is the input to your renderer, which can have one of following types // - golang primitive types (e.g. int, float32) // - map[string]any // - []any // - *yaml.Node // when it's not *yaml.Node type, it was patched by built-in data patching support // (as indicated by the `!` suffix to your renderer) // // Your renderer is responsible for casting it to its desired data type RenderYaml(renderer string, rawData any) (result []byte, err error) }
RenderingHandler is used when resolving yaml fields
type TypeHint ¶ added in v0.3.0
type TypeHint interface { String() string // contains filtered or unexported methods }
type TypeHintBool ¶ added in v0.7.0
type TypeHintBool struct{}
func (TypeHintBool) String ¶ added in v0.7.0
func (TypeHintBool) String() string
type TypeHintFloat ¶ added in v0.3.0
type TypeHintFloat struct{}
func (TypeHintFloat) String ¶ added in v0.5.1
func (TypeHintFloat) String() string
type TypeHintInt ¶ added in v0.3.0
type TypeHintInt struct{}
func (TypeHintInt) String ¶ added in v0.5.1
func (TypeHintInt) String() string
type TypeHintNone ¶ added in v0.3.0
type TypeHintNone struct{}
func (TypeHintNone) String ¶ added in v0.5.1
func (TypeHintNone) String() string
type TypeHintObject ¶ added in v0.3.0
type TypeHintObject struct{}
func (TypeHintObject) String ¶ added in v0.5.1
func (TypeHintObject) String() string
type TypeHintObjects ¶ added in v0.3.0
type TypeHintObjects struct{}
func (TypeHintObjects) String ¶ added in v0.5.1
func (TypeHintObjects) String() string
type TypeHintStr ¶ added in v0.3.0
type TypeHintStr struct{}
func (TypeHintStr) String ¶ added in v0.5.1
func (TypeHintStr) String() string