converter

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 20, 2024 License: Apache-2.0 Imports: 5 Imported by: 4

README

The go-cc-converter package

The go-cc-converter package belongs to the go-cc package family that provides crosscutting layer services. Its sole responsibility is to provide data conversion services through a registry, and converter façade.

A crosscutting layer is a layer within a software architecture that is responsible for handling crosscutting concerns. It provides a centralized location for implementing and managing aspects of the system that cut across multiple components or modules.

Overview

When starting the quick proposal for the conversion function signature is:

func[From any, To any](From) (To, error)

It basically receives the data to be converted, apply the conversion logic and returns the converted value or an error. Soon you will realize this signature works fine when you know how to create an instance of the To data type. For instance, if the To type is an interface and you have an array of bytes, which implementation to use?

Although the signature is fine for most of the cases, you cannot create in Golang a façade to convert any kind of data. The Golang Generics is only available for struct or functions, but not for methods. You cannot create a structure whose methods uses Generics like below:

Facade interface {
	Convert[From any, To any](From) (To, error)
}

The alternative is to remember all conversion functions by name and use it when needed. It is not too bad. Even if you can remember all conversion function names, this approach does not work for libs providing specialized services that have to deal with data conversions where the From and To type are not known upfront and so the generic feature is not feasible.

To help, the go-cc-converter package offers a mixed alternative with a façade conversion function without Generics but with helping functions using Generics. It also provides a registry where all conversion functions with distinct signatures can be registered avoiding you to remember the names of all these functions.

What does the package have?

Interfaces
The converter.Converters interface

The converter.Converters interface is the façade to have access to all conversion functions available.

	Converters interface {
		Convert(from any, to any) error
		ConvertToType(from any, toType reflect.Type) (any, error)
	}

The Convert()/ConvertToType() methods do the following steps:

  1. Identifies the from and to types;
  2. Looks up for a conversion function using the from and to types;
  3. If it finds the conversion function, then it executes the conversion and returns the result;
  4. If no conversion function is found, then it tries many fallbacks to manage a way to do the conversion;
  5. If no fallback succeeds, then returns a not found error.

The library preload many conversion functions but you can add your own functions too. You can also have a special Converters if your app or library need.

The conversion functions provided by the library are in the funcs folder, or the converterfuncs package

The converter.Registry interface

The converter.Registry interface is the contract the registry of conversion function shall implement. It has two basic methods:

package converter

type Registry interface {
    Add(handler Handler) *Handler
    GetConverter(from, to reflect.Type) FromToFunc
	GetConverterTo(from, to reflect.Type) ToFunc
}

The Add() method adds a new conversion function specified by the given Handler. The Handler is the strategy used to avoid mistakes when providing the conversion function to be registered. Registry stores function with the following signature defined by FromToFunc:

package converter

type FromToFunc func(any, any) error

This signature is too wide, it allows any from and any to which it is not real. Even using reflection in Golang it is not possible to identify the real argument types (well, they are any!). To better capture the from and to type and ensure they are not incorrect, the package provides following Handler factories:

package converter

func CreateHandler[From any, To any](converter func(From, *To) error) Handler
func CreateHandlerWithReturn[From any, To any](converter func(From) (To, error)) Handler
func CreateHandlerWithReturnNoError[From any, To any](converter func(From) To) Handler

All these factories capture the from and the to types and make any adjustment needed. They will support almost all conversion functions.

The package provides default Registry instance that can be accessed as shown below:

converterdefault.DefaultRegistry

The converterdefault package provides helper functions to quickly add Handler instances to the default Registry as shown below:

package converterdefault

func AddHandler[From any, To any](fromToFunc func(From, *To) error) {
	DefaultRegistry.Add(converter.CreateHandler[From, To](fromToFunc))
}

func AddHandlerWithReturn[From any, To any](toFunc func(From) (To, error)) {
	DefaultRegistry.Add(converter.CreateHandlerWithReturn[From, To](toFunc))
}

func AddHandlerWithReturnNoError[From any, To any](toFunc func(From) To) {
	DefaultRegistry.Add(converter.CreateHandlerWithReturnNoError[From, To](toFunc))
}

If you need to create a special Registry instance for your application or package with special converters, then you can use the function below that will return the default implementation of Registry:

converterdefault.NewRegistry()

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddFallbacks

func AddFallbacks[From any, To any](registry Registry, fromToFunc func(From, *To) error)

func AddHandler

func AddHandler[From any, To any](registry Registry, fromToFunc func(From, *To) error)

func AddHandlerWithReturn

func AddHandlerWithReturn[From any, To any](registry Registry, toFunc func(From) (To, error))

func AddHandlerWithReturnNoError

func AddHandlerWithReturnNoError[From any, To any](registry Registry, toFunc func(From) To)

func CastOrErr

func CastOrErr[T any](value any) (result T, err error)

func To

func To[T any](registry Converters, f any) (T, error)

Types

type Converters

type Converters interface {
	Convert(from any, to any) error
	ConvertToType(from any, toType reflect.Type) (any, error)
}

Converters is an entity that knows how to convert one value type into another value type.

func NewConvertersList

func NewConvertersList(converters ...Converters) Converters

NewConvertersList returns a Converters implementation that uses the given list of converters to find a function to convert values. If no Converters is provided, the the converter.Defauldefault is used

type ConvertersList

type ConvertersList []Converters

ConvertersList when you have more than one registry and want to use the first one that works

func (ConvertersList) Convert

func (l ConvertersList) Convert(from any, to any) error

func (ConvertersList) ConvertToType

func (l ConvertersList) ConvertToType(from any, toType reflect.Type) (any, error)

type FromToFunc

type FromToFunc func(any, any) error

FromToFunc is a dynamic type conversion function

func MakeFromToFunc

func MakeFromToFunc[F any, T any](converter func(F, *T) error) FromToFunc

func MakeFromToFuncWithReturn

func MakeFromToFuncWithReturn[F any, T any](converter func(F) (T, error)) FromToFunc

type FromToTypedFunc

type FromToTypedFunc[F any, T any] func(F, *T) error

FromToTypedFunc is a strongly typed conversion function from a given F type value to the given T type that should be assigned to the given pointer to T. The given pointer cannot be nil since it should have to receive the converted value.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler is a data structure that provides input type definitions to invoke a FromToFunc function

func CreateHandler

func CreateHandler[From any, To any](converter func(From, *To) error) Handler

func CreateHandlerWithReturn

func CreateHandlerWithReturn[From any, To any](converter func(From) (To, error)) Handler

func CreateHandlerWithReturnNoError

func CreateHandlerWithReturnNoError[From any, To any](converter func(From) To) Handler

func (Handler) GetFromToFunc

func (h Handler) GetFromToFunc() FromToFunc

func (Handler) GetFromType

func (h Handler) GetFromType() reflect.Type

func (Handler) GetToFunc

func (h Handler) GetToFunc() ToFunc

func (Handler) GetToType

func (h Handler) GetToType() reflect.Type

type Registry

type Registry interface {
	// Add adds a new converter to the registry. If there is already one, then the old one is returned and replaced by the new one.
	Add(handler Handler) *Handler

	// GetConverter returns the FromToFunc to be used to convert a `from` value to a `to` value pointer
	GetConverter(from, to reflect.Type) FromToFunc

	// GetConverterTo returns the ToFunc to be used to convert a `from` value to a `to` value
	GetConverterTo(from, to reflect.Type) ToFunc
}

Registry is the entity responsible for keep the FromToFunc instances classified by the `from` and `to` types. Because Golang only supports the Generic feature per structure and not per structure method, we will use functions to register the FromToFunc instances ensuring that Registry knows the `from` and `to` types.

type ToFunc

type ToFunc func(any) (any, error)

ToFunc is a dynamic type conversion function

func MakeToFunc

func MakeToFunc[F any, T any](converter func(F) (T, error)) ToFunc

func MakeToFuncWithArg

func MakeToFuncWithArg[F any, T any](converter func(F, *T) error) ToFunc

type ToTypedFunc

type ToTypedFunc[T any] func(any, *T) error

ToTypedFunc is a partially typed conversion function from any type to a specific type

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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