go-sprout/sprout

View on GitHub
registry/reflect/functions.go

Summary

Maintainability
A
0 mins
Test Coverage
package reflect

import (
    "errors"
    "fmt"
    "reflect"

    "github.com/mitchellh/copystructure"
)

// TypeIs compares the type of 'src' to a target type string 'target'.
// It returns true if the type of 'src' matches the 'target'.
//
// Parameters:
//
//    target string - the string representation of the type to check against.
//    src any - the variable whose type is being checked.
//
// Returns:
//
//    bool - true if 'src' is of type 'target', false otherwise.
//
// Example:
//
//    {{ "int", 42 | typeIs }} // Output: true
func (rr *ReflectRegistry) TypeIs(target string, src any) bool {
    return target == rr.TypeOf(src)
}

// TypeIsLike compares the type of 'src' to a target type string 'target',
// including a wildcard '*' prefix option. It returns true if 'src' matches
// 'target' or '*target'. Useful for checking if a variable is of a specific
// type or a pointer to that type.
//
// Parameters:
//
//    target string - the string representation of the type or its wildcard version.
//    src any - the variable whose type is being checked.
//
// Returns:
//
//    bool - true if the type of 'src' matches 'target' or '*'+target, false otherwise.
//
// Example:
//
//    {{ "*int", 42 | typeIsLike }} // Output: true
func (rr *ReflectRegistry) TypeIsLike(target string, src any) bool {
    t := rr.TypeOf(src)
    return target == t || "*"+target == t
}

// TypeOf returns the type of 'src' as a string.
//
// Parameters:
//
//    src any - the variable whose type is being determined.
//
// Returns:
//
//    string - the string representation of 'src's type.
//
// Example:
//
//    {{ 42 | typeOf }} // Output: "int"
func (rr *ReflectRegistry) TypeOf(src any) string {
    return fmt.Sprintf("%T", src)
}

// KindIs compares the kind of 'src' to a target kind string 'target'.
// It returns true if the kind of 'src' matches the 'target'.
//
// Parameters:
//
//    target string - the string representation of the kind to check against.
//    src any - the variable whose kind is being checked.
//
// Returns:
//
//    bool - true if 'src's kind is 'target', false otherwise.
//    error - when 'src' is nil.
//
// Example:
//
//    {{ "int", 42 | kindIs }} // Output: true
func (rr *ReflectRegistry) KindIs(target string, src any) (bool, error) {
    result, err := rr.KindOf(src)
    if err != nil {
        return false, err
    }

    return result == target, nil
}

// KindOf returns the kind of 'src' as a string.
//
// Parameters:
//
//    src any - the variable whose kind is being determined.
//
// Returns:
//
//    string - the string representation of 'src's kind.
//    error - when 'src' is nil.
//
// Example:
//
//    {{ 42 | kindOf }} // Output: "int"
func (rr *ReflectRegistry) KindOf(src any) (string, error) {
    if src == nil {
        return "", errors.New("src must not be nil")
    }

    return reflect.ValueOf(src).Kind().String(), nil
}

// HasField checks whether a struct has a field with a given name.
//
// Parameters:
//
//    name string - the name of the field that is being checked.
//    src any - the struct that is being checked.
//
// Returns:
//
//    bool - true if the struct 'src' contains a field with the name 'name', false otherwise.
//    error - when the last argument is not a struct.
//
// Example:
//
//    {{ hasField "someExistingField" .someStruct }} // Output: true
//    {{ hasField "someNonExistingField" .someStruct }} // Output: false
func (rr *ReflectRegistry) HasField(name string, src any) (bool, error) {
    rv := reflect.Indirect(reflect.ValueOf(src))
    if rv.Kind() != reflect.Struct {
        return false, errors.New("last argument must be a struct")
    }
    return rv.FieldByName(name).IsValid(), nil
}

// DeepEqual determines if two variables, 'x' and 'y', are deeply equal.
// It uses reflect.DeepEqual to evaluate equality.
//
// Parameters:
//
//    x, y any - the variables to be compared.
//
// Returns:
//
//    bool - true if 'x' and 'y' are deeply equal, false otherwise.
//
// Example:
//
//    {{ {"a":1}, {"a":1} | deepEqual }} // Output: true
func (rr *ReflectRegistry) DeepEqual(x, y any) bool {
    return reflect.DeepEqual(y, x)
}

// DeepCopy performs a deep copy of 'element' and panics if copying fails.
// It relies on MustDeepCopy to perform the copy and handle errors internally.
//
// Parameters:
//
//    element any - the element to be deeply copied.
//
// Returns:
//
//    any - a deep copy of 'element'.
//    error - when 'element' is nil.
//
// Example:
//
//    {{ {"name":"John"} | deepCopy }} // Output: {"name":"John"}
func (rr *ReflectRegistry) DeepCopy(element any) (any, error) {
    if element == nil {
        return nil, errors.New("element cannot be nil")
    }
    return copystructure.Copy(element)
}