Documentation
¶
Index ¶
- func CompareValues(v1, v2 reflect.Value, op string, ignoreCase bool) (bool, error)
- func ConvertValue(v reflect.Value, targetType reflect.Type) reflect.Value
- func ConvertValueChecked(v reflect.Value, targetType reflect.Type) (reflect.Value, error)
- func ConvertValueVerified(v reflect.Value, targetType reflect.Type) (reflect.Value, bool)
- func Copy[T any](src T, opts ...CopyOption) (T, error)
- func CopyShared(src any, pointers PointersMap) (any, error)
- func DeepCopyValue(v reflect.Value) reflect.Value
- func Dereference(v reflect.Value) (reflect.Value, error)
- func Equal[T any](a, b T, opts ...EqualOption) bool
- func EqualCoerced(current reflect.Value, expected any) bool
- func EqualCoercedValue(current, ev reflect.Value) bool
- func EscapeKey(key string) string
- func ExtractKey(v reflect.Value, fieldIdx int) any
- func GetKeyField(typ reflect.Type) (int, bool)
- func JoinPath(parent, child string) string
- func MustCopy[T any](src T, opts ...CopyOption) T
- func NormalizePath(path string) string
- func RegisterCustomCopy(typ reflect.Type, fn reflect.Value)
- func RegisterCustomEqual(typ reflect.Type, fn reflect.Value)
- func SetValue(v, newVal reflect.Value)
- func UnescapeKey(token string) string
- func ValueEqual(a, b reflect.Value, config *equalConfig) bool
- func ValueToInterface(v reflect.Value) any
- type Copier
- type CopyOption
- type DeepPath
- func (p DeepPath) Delete(v reflect.Value) error
- func (p DeepPath) Navigate(v reflect.Value, parts []PathPart) (reflect.Value, PathPart, error)
- func (p DeepPath) Resolve(v reflect.Value) (reflect.Value, error)
- func (p DeepPath) ResolveMember(v reflect.Value) (reflect.Value, error)
- func (p DeepPath) ResolveParent(v reflect.Value) (reflect.Value, PathPart, error)
- func (p DeepPath) ResolveParentPath() (DeepPath, PathPart, error)
- func (p DeepPath) Set(v reflect.Value, val reflect.Value) error
- type EqualOption
- type FieldInfo
- type PathPart
- type PointersMap
- type PointersMapKey
- type RawValue
- type StructTag
- type TypeInfo
- type VisitKey
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CompareValues ¶
func ConvertValueChecked ¶
ConvertValueChecked is ConvertValue with a verdict: it reports an error instead of handing back a value the caller would panic on when setting. Patch values routinely come from untrusted input (a JSON document from a peer), so a type mismatch has to be an error, never a panic.
func ConvertValueVerified ¶
ConvertValueVerified converts v to targetType, refusing conversions that lose information.
Only a numeric conversion needs verifying, and it needs it badly: float64(5.7) converts to int(5), which would otherwise pass for a field holding 5. Converting back has to reproduce what was given. The other conversions this performs are not reversible and do not need to be — a map[string]any decoding into a struct has no meaningful conversion back, and no truncation to hide: the decode either produces the value or it fails.
func Copy ¶
func Copy[T any](src T, opts ...CopyOption) (T, error)
Copy creates a deep copy of src. It returns the copy and a nil error in case of success and the zero value for the type and a non-nil error on failure.
It correctly handles cyclic references and unexported fields.
func CopyShared ¶
func CopyShared(src any, pointers PointersMap) (any, error)
CopyShared deep-copies src recording into (and honouring) the caller's pointers map instead of a private one. Passing the same map across several copies makes them one copy for sharing purposes: a value any of them has already copied is reused, not copied again. Generated Clone code threads its memo through here for the fields it cannot copy itself.
func Equal ¶
func Equal[T any](a, b T, opts ...EqualOption) bool
Equal performs a deep equality check between a and b.
func EqualCoerced ¶
EqualCoerced reports whether current equals expected, where expected may be of a different but losslessly convertible type.
Operation.Old and a condition's Value are declared `any`, so a patch that travelled as JSON carries whatever the decoder produced: every number arrives as float64 regardless of the field's type. Comparing those with Equal, which requires identical types, reports a mismatch for every numeric field — which is why a strict check on a decoded patch used to fail against state it actually matched.
Converting before comparing fixes that, but a bare conversion truncates: float64(5.7) becomes int(5), which would then compare equal to a field holding 5. The conversion is therefore verified by converting back — only a value that survives the round trip unchanged is accepted as comparable.
func EqualCoercedValue ¶
EqualCoercedValue is EqualCoerced over two reflect.Values. Conditions use it so that == and != mean the same thing there as in a strict check.
func MustCopy ¶
func MustCopy[T any](src T, opts ...CopyOption) T
MustCopy creates a deep copy of src. It returns the copy on success or panics in case of any failure.
It correctly handles cyclic references and unexported fields.
func NormalizePath ¶
NormalizePath converts a dot-notation or JSON Pointer path to a standard JSON Pointer.
func RegisterCustomCopy ¶
RegisterCustomCopy registers a custom copy function for a specific type. The function must be of type func(src T) (T, error).
func RegisterCustomEqual ¶
RegisterCustomEqual registers a custom equality function for a specific type. The function must be of type func(a, b T) bool.
func UnescapeKey ¶
UnescapeKey reverses EscapeKey, turning the RFC 6901 escape sequences "~1" and "~0" back into "/" and "~". The order (slash first) matters: unescaping "~0" first would turn "~01" into "~1" and then wrongly into "/".
func ValueEqual ¶
ValueEqual performs a deep equality check between two reflect.Values.
func ValueToInterface ¶
Types ¶
type Copier ¶
Copier is an interface that types can implement to provide their own custom deep copy logic. The type T in Copy() (T, error) must be the same concrete type as the receiver that implements this interface.
type CopyOption ¶
type CopyOption interface {
// contains filtered or unexported methods
}
CopyOption allows configuring the behavior of the Copy function.
func CopyIgnorePath ¶
func CopyIgnorePath(path string) CopyOption
CopyIgnorePath returns an option that tells Copy to ignore the specified path. The ignored path will have the zero value for its type in the resulting copy.
func SkipUnsupported ¶
func SkipUnsupported() CopyOption
SkipUnsupported returns an option that tells Copy to skip unsupported types (like non-nil functions or channels) instead of returning an error.
type DeepPath ¶
type DeepPath string
DeepPath represents a path to a field or element within a structure. It supports JSON Pointers (RFC 6901) syntax like "/Field/SubField".
func (DeepPath) ResolveMember ¶
ResolveMember resolves the path to the member the last segment names — the struct field, map value, or slice element itself — without dereferencing it. Resolve returns the value a pointer member points at; alias operations need the pointer, because their whole purpose is to install that same reference somewhere else.
func (DeepPath) ResolveParent ¶
func (DeepPath) ResolveParentPath ¶
ResolveParentPath splits the path into parent path and the last part.
type EqualOption ¶
type EqualOption interface {
// contains filtered or unexported methods
}
EqualOption allows configuring the behavior of the Equal function.
func EqualIgnorePath ¶
func EqualIgnorePath(path string) EqualOption
EqualIgnorePath returns an option that tells Equal to ignore the specified path.
type PathPart ¶
func ParseJSONPointer ¶
type PointersMap ¶
type PointersMap map[PointersMapKey]reflect.Value
PointersMap records the copy made for each value during one deep copy. It is exported so a copy can be run against a caller-provided map: generated Clone code and the reflection engine share one map, which is what keeps a value referenced from both sides copied exactly once.
type PointersMapKey ¶
PointersMapKey identifies one already-copied value: the address it lives at and the type it was reached as. The type matters because pointers of different types can share an address — a struct and its first field — and must not be mistaken for one another.
type RawValue ¶
type RawValue struct {
JSON []byte
}
RawValue holds a value that arrived over the wire and has not been decoded yet, because the right type to decode it into is not known until the operation carrying it reaches its target field.
This is what removes a whole class of coercion bugs. Decoding an untyped value produces whatever the decoder's defaults are — every JSON number a float64, every object a map[string]any, every []byte a base64 string — and the library then had to guess its way back to the field's real type, verified conversion by verified conversion, each one a place to be wrong. Decoding into the field's actual type instead makes the decoder itself do the right thing by construction.
func (RawValue) MarshalJSON ¶
MarshalJSON emits the still-encoded bytes as they are, so a re-serialized operation is byte-identical to the one that arrived.
func (*RawValue) UnmarshalJSON ¶
UnmarshalJSON captures the encoded bytes without interpreting them.