laser

package
v0.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 20, 2024 License: BSD-3-Clause Imports: 15 Imported by: 0

README

laser: reflection optimized

Go Report Card pkg.go.dev docs

Package laser is a highly reflective package of golang reflect helpers (lasers work by bouncing light back and forth between two mirrors). It also connotes the "lazy" aspect of reflection -- running dynamically instead of statically precompiled. It is derived from the ki/kit package in v1 of ki.

As usual, Go reflect provides just the minimal API for dealing with reflection, and there are several well-documented issues that require a bit of non-obvious logic to get around.

Some example functions:

  • AnyIsNil() -- checks if interface value is nil -- requires extra logic for multiple levels of nil.

  • ToInt, ToFloat, ToString, ToBool -- robustly converts any value to given type, using an efficient type switch for all basic types, including pointers, and using strconv parse from string. See also glop/num for generics-based conversion. The key difference is that if you have an any, you can't use generics, so these type-switch methods are necessary in that case.

  • SetRobust(to, frm any) bool -- robustly sets the 'to' value from the 'from' value, for any case, using the To* functions and JSON format for maps and slices.

  • UnhideAnyValue(v reflect.Value) reflect.Value -- ensures value is actually assignable -- e.g., reflect.Make* functions return a pointer to the new object, but it is hidden behind an interface{} and this magic code extracts the actual underlying value

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllFields

func AllFields(typ reflect.Type) []reflect.StructField

AllFields returns a slice list of all the StructField type information for all elemental fields of given type and all embedded types -- returns nil on error (logged)

func AllFieldsN

func AllFieldsN(typ reflect.Type) int

AllFieldsN returns number of elemental fields in given type

func AllFieldsTypeFunc

func AllFieldsTypeFunc(typ reflect.Type, fun func(typ reflect.Type, field reflect.StructField) bool) bool

AllFieldsTypeFunc calls a function on all the fields of a given struct type, including those on *any* fields of struct fields that this struct has -- if fun returns false then iteration stops -- overall rval is false if iteration was stopped or there was an error (logged), true otherwise.

func AnyIsNil

func AnyIsNil(it any) bool

AnyIsNil checks if an interface value is nil -- the interface itself could be nil, or the value pointed to by the interface could be nil -- this checks both, safely gopy:interface=handle

func CloneToType

func CloneToType(typ reflect.Type, val any) reflect.Value

CloneToType creates a new object of given type, and uses SetRobust to copy an existing value (of perhaps another type) into it

func CopyMapRobust

func CopyMapRobust(to, fm any) error

CopyMapRobust robustly copies maps using SetRobust method for the elements.

func CopySliceRobust

func CopySliceRobust(to, fm any) error

CopySliceRobust robustly copies slices using SetRobust method for the elements.

func Embed

func Embed(stru any, embed reflect.Type) any

Embed returns the embedded struct of given type within given struct

func EmbedImplements

func EmbedImplements(typ, iface reflect.Type) bool

EmbedImplements checks if given type implements given interface, or it embeds a type that does so -- must pass a type constructed like this: reflect.TypeOf((*gi.Node2D)(nil)).Elem() or just reflect.TypeOf(laser.BaseIface())

func FieldByPath

func FieldByPath(typ reflect.Type, path string) (reflect.StructField, bool)

FieldByPath returns field in type or embedded structs within type, by a dot-separated path -- finds field by name for each level of the path, and recurses.

func FieldValueByPath

func FieldValueByPath(stru any, path string) (reflect.Value, bool)

FieldValueByPath returns field interface in type or embedded structs within type, by a dot-separated path -- finds field by name for each level of the path, and recurses.

func FlatFieldByName

func FlatFieldByName(typ reflect.Type, nm string) (reflect.StructField, bool)

FlatFieldByName returns field in type or embedded structs within type, by name -- native function already does flat version, so this is just for reference and consistency

func FlatFieldInterfaceByName

func FlatFieldInterfaceByName(stru any, nm string) any

FlatFieldInterfaceByName finds field in object and embedded objects, by name, returning interface{} to pointer of field, or nil if not found

func FlatFieldInterfaces

func FlatFieldInterfaces(stru any) []any

FlatFieldInterfaces returns a slice list of all the field interface{} values *as pointers to the field value* (i.e., calling Addr() on the Field Value) for fields of given struct (must pass a pointer to the struct) and any of its embedded structs -- returns nil on error (logged)

func FlatFieldTag

func FlatFieldTag(typ reflect.Type, nm, tag string) string

FlatFieldTag returns given tag value in field in type or embedded structs within type, by name -- empty string if not set or field not found

func FlatFieldVals

func FlatFieldVals(stru any) []reflect.Value

FlatFieldsVals returns a slice list of all the field reflect.Value's for fields of given struct (must pass a pointer to the struct) and any of its embedded structs -- returns nil on error (logged)

func FlatFieldValueByName

func FlatFieldValueByName(stru any, nm string) reflect.Value

FlatFieldValueByName finds field in object and embedded objects, by name, returning reflect.Value of field -- native version of Value function already does flat find, so this just provides a convenient wrapper

func FlatFields

func FlatFields(typ reflect.Type) []reflect.StructField

FlatFields returns a slice list of all the StructField type information for fields of given type and any embedded types -- returns nil on error (logged)

func FlatFieldsTypeFunc

func FlatFieldsTypeFunc(typ reflect.Type, fun func(typ reflect.Type, field reflect.StructField) bool) bool

FlatFieldsTypeFunc calls a function on all the primary fields of a given struct type, including those on anonymous embedded structs that this struct has, passing the current (embedded) type and StructField -- effectively flattens the reflect field list -- if fun returns false then iteration stops -- overall rval is false if iteration was stopped or there was an error (logged), true otherwise

func FlatFieldsTypeFuncIf

func FlatFieldsTypeFuncIf(typ reflect.Type, ifFun, fun func(typ reflect.Type, field reflect.StructField) bool) bool

FlatFieldsTypeFunc calls a function on all the primary fields of a given struct type, including those on anonymous embedded structs that this struct has, passing the current (embedded) type and StructField -- effectively flattens the reflect field list -- if fun returns false then iteration stops -- overall rval is false if iteration was stopped or there was an error (logged), true otherwise. If the given ifFun is non-nil, it is called on every embedded struct field to determine whether the fields of that embedded field should be handled (a return value of true indicates to continue down and a value of false indicates to not).

func FlatFieldsValueFunc

func FlatFieldsValueFunc(stru any, fun func(stru any, typ reflect.Type, field reflect.StructField, fieldVal reflect.Value) bool) bool

FlatFieldsValueFunc calls a function on all the primary fields of a given struct value (must pass a pointer to the struct) including those on anonymous embedded structs that this struct has, passing the current (embedded) type and StructField, which effectively flattens the reflect field list.

func FlatFieldsValueFuncIf

func FlatFieldsValueFuncIf(stru any, ifFun, fun func(stru any, typ reflect.Type, field reflect.StructField, fieldVal reflect.Value) bool) bool

FlatFieldsValueFunc calls a function on all the primary fields of a given struct value (must pass a pointer to the struct) including those on anonymous embedded structs that this struct has, passing the current (embedded) type and StructField, which effectively flattens the reflect field list. If the given ifFun is non-nil, it is called on every embedded struct field to determine whether the fields of that embedded field should be handled (a return value of true indicates to continue down and a value of false indicates to not).

func FormatDefault

func FormatDefault(def string) string

FormatDefault converts the given `default:` struct tag string into a format suitable for being used as a value in SetRobust. If it returns "", the default value should not be used.

func FriendlyTypeName

func FriendlyTypeName(typ reflect.Type) string

FriendlyTypeName returns a user-friendly version of the name of the given type. It transforms it into sentence case, excludes the package, and converts various builtin types into more friendly forms (eg: "int" to "Number").

func KindIsBasic

func KindIsBasic(vk reflect.Kind) bool

KindIsBasic returns true if the reflect.Kind is a basic, elemental type such as Int, Float, etc

func LongTypeName

func LongTypeName(typ reflect.Type) string

LongTypeName returns the long, full package-path qualified type name. This is guaranteed to be unique and used for internal storage of several maps to avoid any conflicts. It is also very quick to compute.

func MakeMap

func MakeMap(typ reflect.Type) reflect.Value

MakeMap makes a map that is actually addressable, getting around the hidden interface{} that reflect.MakeMap makes, by calling UnhideIfaceValue (from ptrs.go)

func MakeOfType

func MakeOfType(typ reflect.Type) reflect.Value

MakeOfType creates a new object of given type with appropriate magic foo to make it usable

func MakeSlice

func MakeSlice(typ reflect.Type, len, cap int) reflect.Value

MakeSlice makes a map that is actually addressable, getting around the hidden interface{} that reflect.MakeSlice makes, by calling UnhideAnyValue (from ptrs.go)

func MapAdd

func MapAdd(mv any)

MapAdd adds a new blank entry to the map

func MapDelete

func MapDelete(mv any, key any)

MapDelete deletes a key-value from the map (set key to a zero value)

func MapDeleteAll

func MapDeleteAll(mv any)

MapDeleteAll deletes everything from map

func MapDeleteValue

func MapDeleteValue(mv any, key reflect.Value)

MapDeleteValue deletes a key-value from the map (set key to a zero value) -- key is already a reflect.Value

func MapElsN

func MapElsN(mp any) int

MapElsN returns number of elemental fields in given map type

func MapElsValueFun

func MapElsValueFun(mp any, fun func(mp any, typ reflect.Type, key, val reflect.Value) bool) bool

MapElsValueFun calls a function on all the "basic" elements of given map -- iterates over maps within maps (but not structs, slices within maps).

func MapKeyType

func MapKeyType(mp any) reflect.Type

MapKeyType returns the type of the key for the given map (which can be a pointer to a map or a direct map) -- just Key() of map type, but using this function makes it more explicit what is going on.

func MapSort

func MapSort(mp any, byKey, ascending bool) []reflect.Value

MapSort sorts keys of map either by key or by value, returns those keys as a slice of reflect.Value, as returned by reflect.Value.MapKeys() method

func MapStructElsN

func MapStructElsN(mp any) int

MapStructElsN returns number of elemental fields in given map / struct types

func MapStructElsValueFun

func MapStructElsValueFun(mp any, fun func(mp any, typ reflect.Type, val reflect.Value) bool) bool

MapStructElsValueFun calls a function on all the "basic" elements of given map or struct -- iterates over maps within maps and fields within structs

func MapValueSort

func MapValueSort(mpvnp reflect.Value, keys []reflect.Value, ascending bool) error

MapValueSort sorts keys of map by values

func MapValueType

func MapValueType(mp any) reflect.Type

MapValueType returns the type of the value for the given map (which can be a pointer to a map or a direct map) -- just Elem() of map type, but using this function makes it more explicit what is going on.

func NonDefaultFields

func NonDefaultFields(v any) map[string]any

NonDefaultFields returns a map representing all of the fields of the given struct (or pointer to a struct) that have values different than their default values as specified by the `default:` struct tag. The resulting map is then typically saved using something like JSON or TOML. If a value has no default value, it checks whether its value is non-zero. If a field has a `save:"-"` tag, it wil not be included in the resulting map.

func NonPtrInterface

func NonPtrInterface(el any) any

NonPtrInterface returns the non-pointer value of an interface

func NonPtrType

func NonPtrType(typ reflect.Type) reflect.Type

NonPtrType returns the non-pointer underlying type

func NonPtrValue

func NonPtrValue(v reflect.Value) reflect.Value

NonPtrValue returns the non-pointer underlying value

func OnePtrInterface

func OnePtrInterface(el any) any

OnePtrInterface returns the pointer value of an interface, if it is possible to get one through Addr()

func OnePtrType

func OnePtrType(typ reflect.Type) reflect.Type

OnePtrType returns a type that is exactly one pointer away from a non-pointer type

func OnePtrUnderlyingValue

func OnePtrUnderlyingValue(v reflect.Value) reflect.Value

OnePtrUnderlyingValue returns a value that is exactly one pointer away from a non-pointer type, and also goes through an interface to find the actual underlying type behind the interface.

func OnePtrValue

func OnePtrValue(v reflect.Value) reflect.Value

OnePtrValue returns a value that is exactly one pointer away from a non-pointer type

func PtrInterface

func PtrInterface(el any) any

PtrInterface returns the pointer value of an interface, if it is possible to get one through Addr()

func PtrType

func PtrType(typ reflect.Type) reflect.Type

PtrType returns the pointer type for given type, if given type is not already a Ptr

func PtrValue

func PtrValue(v reflect.Value) reflect.Value

PtrValue returns the pointer version (Addr()) of the underlying value if the value is not already a Ptr

func SetField

func SetField(obj any, field string, val any) error

SetField sets given field name on given struct object to given value, using very robust conversion routines to e.g., convert from strings to numbers, and vice-versa, automatically. Returns error if not successfully set.

func SetFromDefaultTag added in v0.0.6

func SetFromDefaultTag(v reflect.Value, def string) error

SetFromDefaultTag sets the given value from the given default tag.

func SetFromDefaultTags

func SetFromDefaultTags(obj any) error

SetFromDefaultTags sets values of fields in given struct based on `default:` default value field tags.

func SetMapRobust

func SetMapRobust(mp, ky, val reflect.Value) bool

SetMapRobust robustly sets a map value using reflect.Value representations of the map, key, and value elements, ensuring that the proper types are used for the key and value elements using sensible conversions. map value must be a valid map value -- that is not checked.

func SetRobust

func SetRobust(to, frm any) error

SetRobust robustly sets the 'to' value from the 'from' value. destination must be a pointer-to. Copies slices and maps robustly, and can set a struct, slice or map from a JSON-formatted string from value. Note that a map is _not_ reset prior to setting, whereas a slice length is set to the source length and is thus equivalent to the source slice.

func ShortTypeName

func ShortTypeName(typ reflect.Type) string

ShortTypeName returns the short version of a package-qualified type name which just has the last element of the path. This is what is used in standard Go programming, and is is used for the key to lookup reflect.Type names -- i.e., this is what you should save in a JSON file. The potential naming conflict is worth the brevity, and typically a given file will only contain mutually-compatible, non-conflicting types. This is cached in ShortNames because the path.Base computation is apparently a bit slow.

func SliceDeleteAt

func SliceDeleteAt(sl any, idx int)

SliceDeleteAt deletes element at given index from slice

func SliceElType

func SliceElType(sl any) reflect.Type

SliceElType returns the type of the elements for the given slice (which can be a pointer to a slice or a direct slice) -- just Elem() of slice type, but using this function makes it more explicit what is going on. And it uses OnePtrUnderlyingValue to get past any interface wrapping.

func SliceElValue

func SliceElValue(sl any) reflect.Value

SliceElValue returns a reflect.Value of the Slice element type. isPtr indicates that the value is a Pointer type, in which case a concrete element has been made and the value is a pointer to it.

func SliceNewAt

func SliceNewAt(sl any, idx int)

SliceNewAt inserts a new blank element at given index in the slice. -1 means the end.

func SliceSort

func SliceSort(sl any, ascending bool) error

SliceSort sorts a slice of basic values (see StructSliceSort for sorting a slice-of-struct using a specific field), using float, int, string conversions (first fmt.Stringer String()) and supporting time.Time directly as well.

func StringJSON

func StringJSON(it any) string

StringJSON returns a JSON representation of item, as a string e.g., for printing / debugging etc.

func StructSliceSort

func StructSliceSort(struSlice any, fldIdx []int, ascending bool) error

StructSliceSort sorts a slice of a struct according to the given field indexes and sort direction, using float, int, string conversions (first fmt.Stringer String()) and supporting time.Time directly as well. There is no direct method for checking the field indexes so those are assumed to be accurate -- will panic if not!

func StructTags

func StructTags(tags reflect.StructTag) map[string]string

StructTags returns a map[string]string of the tag string from a reflect.StructTag value e.g., from StructField.Tag

func ToBool

func ToBool(v any) (bool, error)

ToBool robustly converts to a bool any basic elemental type (including pointers to such) using a big type switch organized for greatest efficiency. It tries the cogentcore.org/core/glop/bools.Booler interface if not a bool type. It falls back on reflection when all else fails.

func ToFloat

func ToFloat(v any) (float64, error)

ToFloat robustly converts to a float64 any basic elemental type (including pointers to such) using a big type switch organized for greatest efficiency, only falling back on reflection when all else fails.

func ToFloat32

func ToFloat32(v any) (float32, error)

ToFloat32 robustly converts to a float32 any basic elemental type (including pointers to such) using a big type switch organized for greatest efficiency, only falling back on reflection when all else fails.

func ToInt

func ToInt(v any) (int64, error)

ToInt robustly converts to an int64 any basic elemental type (including pointers to such) using a big type switch organized for greatest efficiency, only falling back on reflection when all else fails.

func ToString

func ToString(v any) string

ToString robustly converts anything to a String using a big type switch organized for greatest efficiency. First checks for string or []byte and returns that immediately, then checks for the Stringer interface as the preferred conversion (e.g., for enums), and then falls back on strconv calls for numeric types. If everything else fails, it uses Sprintf("%v") which always works, so there is no need for an error return value.

  • returns "nil" for any nil pointers
  • byte is converted as string(byte) not the decimal representation

func ToStringPrec

func ToStringPrec(v any, prec int) string

ToStringPrec robustly converts anything to a String using given precision for converting floating values -- using a value like 6 truncates the nuisance random imprecision of actual floating point values due to the fact that they are represented with binary bits. Otherwise is identical to ToString for any other cases.

func TypeEmbeds

func TypeEmbeds(typ, embed reflect.Type) bool

TypeEmbeds checks if given type embeds another type, at any level of recursive embedding (including being the type itself)

func UnhideAnyValue

func UnhideAnyValue(v reflect.Value) reflect.Value

UnhideAnyValue returns a reflect.Value for any of the Make* functions that is actually assignable -- even though these functions return a pointer to the new object, it is somehow hidden behind an interface{} and this magic code, posted by someone somewhere that I cannot now find again, un-hides it..

func ValueSliceSort

func ValueSliceSort(sl []reflect.Value, ascending bool) error

ValueSliceSort sorts a slice of reflect.Values using basic types where possible

Types

type SetAnyer

type SetAnyer interface {
	SetAny(v any) error
}

SetAnyer represents a type that can be set from any value. It is checked in SetRobust.

type SetStringer

type SetStringer interface {
	SetString(s string) error
}

SetStringer represents a type that can be set from a string value. It is checked in SetRobust.

type SortInter

type SortInter interface {
	Int() int64
}

SortInter looks for Int() method for sorting

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL