Giter VIP home page Giter VIP logo

go-tupleconv's Introduction

Tarantool tuples converter in Go

Go Reference Actions Status Code Coverage

Table of contents

Documentation

Converter

Converter[S,T] converts objects of type S into objects of type T. Converters are basic entities on which mappers are based.
Implementations of some converters are available, for example, converters from strings to golang types.
Usage example:

// Basic converter.
strToBoolConv := tupleconv.MakeStringToBoolConverter()
result, err := strToBoolConv.Convert("true") // true <nil>

// Function based converter.
funcConv := tupleconv.MakeFuncConverter(func(s string) (string, error) {
    return s + " world!", nil
})
result, err = funcConv.Convert("hello") // hello world! <nil>

Note 1: You can use the provided converters.

Note 2: You can create your own converters based on the functions with tupleconv.MakeFuncConverter.

Note 3: You can create your own converters, implementing Converter[S,T] interface.

Mapper

Mapper is an object that converts tuples. It is built using a list of converters.
Usage example:

// Mapper example.
mapper := tupleconv.MakeMapper[string, any]([]tupleconv.Converter[string, any]{
    tupleconv.MakeFuncConverter(func(s string) (any, error) {
        return s + "1", nil
    }),
    tupleconv.MakeFuncConverter(func(s string) (any, error) {
        iVal, err := strconv.Atoi(s)
        if err != nil {
            return nil, errors.New("can't convert")
        }
	return iVal + 1, nil
    }),
})
result, err := mapper.Map([]string{"a", "4"}) // []any{"a1", 5} <nil>
result, err = mapper.Map([]string{"0"}) // []any{"01"} <nil>
// Single mapper example.
toStringMapper := tupleconv.MakeMapper([]tupleconv.Converter[any, string]{}).
        WithDefaultConverter(tupleconv.MakeFuncConverter(
            func(s any) (string, error) {
                return fmt.Sprintln(s), nil
        }),
)
res, err := toStringMapper.Map([]any{1, 2.5, nil}) // ["1\n", "2.5\n", "<nil>\n"] <nil>

Note 1: To create a mapper, an array of converters is needed, each of which transforms a certain type S into type T.

Note 2: To perform tuple mapping, you can use the function Map, which will return control to the calling code upon the first error.

Note 3: You can set a default converter that will be applied if the tuple length exceeds the size of the primary converters list.
For example, if you only set a default converter, Map will work like the map function in functional programming languages.

Note 4: If tuple length is less than converters list length, then only corresponding converters will be applied.

Mappers to tarantool types

Example

For building an array of converters, especially when it comes to conversions to tarantool types, there is a built-in solution.
Let's consider an example:

factory := tupleconv.MakeStringToTTConvFactory().
                WithDecimalSeparators(",.")

spaceFmt := []tupleconv.SpaceField{
    {Type: tupleconv.TypeUnsigned},
    {Type: tupleconv.TypeDouble, IsNullable: true},
    {Type: tupleconv.TypeString},
}

converters, _ := tupleconv.MakeTypeToTTConverters[string](factory, spaceFmt)
mapper := tupleconv.MakeMapper(converters)
result, err := mapper.Map([]string{"1", "-2,2", "some_string"}) // [1, -2.2, "some_string"] <nil>

Note 1: To build an array of converters, the space format and a certain object implementing TTConvFactory are used. Function MakeTypeToTTConverters takes these entities and gives the converters list.

Note 2: TTConvFactory[Type] is capable of building a converter from Type to each tarantool type.

Note 3: There is a basic factory available called StringToTTConvFactory, which is used for conversions from strings to tarantool types.

Note 4: StringToTTConvFactory can be configured with options like WithDecimalSeparators.

String to nullable

When converting nullable types with StringToTTConvFactory, first, an attempt is made to convert to null.

For example, empty string is interpreted like null with default options. If a field has a string type and is nullable, then an empty string will be converted to null during the conversion process, rather than being converted to empty string.

String to any/scalar

When converting to any/scalar with StringToTTConvFactory, by default, an attempt will be made to convert them to the following types, in the following order:

  • number
  • decimal
  • boolean
  • datetime
  • uuid
  • interval
  • string

Customization

TTConvFactory[Type] is an interface that can build a mapper from Type to each tarantool type.
To customize the behavior for specific types, one can inherit from the existing factory and override the necessary methods.
For example, let's make the standard factory for conversion from strings to tarantool types always convert any type to a string:

type customFactory struct {
    tupleconv.StringToTTConvFactory
}

func (f *customFactory) MakeTypeToAnyMapper() tupleconv.Converter[string, any] {
    return tupleconv.MakeFuncConverter(func(s string) (any, error) {
        return s, nil
    })
}

func example() {
    factory := &customFactory{}
    spaceFmt := []tupleconv.SpaceField{{Type: "any"}}
    converters, _ := tupleconv.MakeTypeToTTConverters[string](factory, spaceFmt)

    res, err := converters[0].Convert("12") // "12" <nil>
}

go-tupleconv's People

Contributors

askalt avatar

Stargazers

Leonid Vasilev avatar

Watchers

Alexander Turenko avatar Borislav Demidov avatar Yaroslav Lobankov avatar Georgy Moiseev avatar Oleg Jukovec avatar  avatar Leonid Vasilev avatar  avatar

go-tupleconv's Issues

API (and internals) introducing

raw parsers

There are several raw parsers that parse strings and convert them into various types (bool, uint64, int64, and so on). These parsers can be used as utilities for writing custom parsers.

For example:

func BoolParser(s string) (bool, error) 

Additionally, there is a function for combining parsers and applying them in a certain order:

func MakeCompositeParser(parsers []Parser) Parser

Converter

Converter is the main type for constructing various converters. It is a abstract object, and its entire interface consists of one function:

 Convert(val any, typ TypeName, isNullable bool) (any, error)

All this function does is find the conversion function in the conversion table based on the type name that needs to be executed for the conversion.
The entire converter's functionality is configured using a Config, which looks like this:

type Config struct {
	// DecSeparators are decimal separators.
	DecSeparators string
	// ThousandSeparators separate thousands.
	ThousandSeparators string
	// NullValue is a string interpreted as null.
	NullValue string

	// ConvertTable is a table, containing convert rules.
	ConvertTable map[TypeName]TypeConverter
}

The ConvertTable allows flexible customization. It is a mapping from type names to TypeConverter, which is declared as follows:

type TypeConverter func(any, Config, bool) (any, error)

Exactly, the TypeConverter is a function that implements a certain type conversion. As you mentioned, its behavior can depend on the values from the Config. For example, a standard parser for converting strings to tarantool types will use the specified values from the configuration to perform the conversions.
Third argument of TypeConverter is isNullable flag, which is true, when this value can be null.

There are several built-in standard configs that cover the main use cases of the converter. These include:

  • TTDecoderConfig, which converts from string to tarantool types
  • TTEncoderConfig, which converts from tarantool types to string

Samples

For example, this is how you can create the most basic converter from strings to tarantool types:

decoder := tupleconv.NewConverter(tupleconv.TTDecoderConfig)

If custom settings are needed, you can do the following:

decodeTable := tupleconv.TTDecodeTable
decodeTable["strange"] = func(s any, _ tupleconv.Config, isNullable bool) (any, error) {
	return s.(string) + "1", nil
}

decoder := tupleconv.NewConverter(tupleconv.Config{
	DecSeparators:        ".*",
	ThousandSeparators:   "@ '",
	NullValue:            "null",
	DecodeTable:          decodeTable,
})

Here is how the creation of an encoder looks like:

encoder := tupleconv.NewConverter(tupleconv.TTEncoderConfig)

TupleConverter

TupleConverter is a helper type that allows converting spaces according to their format. To create it, you need to pass the parsed format of the space, as well as a specific converter.

NewTupleConverter(conv *Converter, spaceFmt []FieldFmt) *TupleDecoder

It provides a function for converting a tuple according to the format:

Decode(tuple any) ([]any, error)

For example, here's how you can create a parser for spaces (using converter with TTDecoderConfig as converter):

tupleFormat := []any{
	map[any]any{"type": "unsigned"},
	map[any]any{"type": "integer", "is_nullable": true},
}
fmt, _ := tupleconv.ParseSpaceFmt(tupleFormat)

tupleDecoder := tupleconv.NewTupleConverter(
	tupleconv.NewConverter(tupleconv.TTDecoderConfig), fmt,
)

tup, _ := tupleDecoder.Convert([]string{"1", "null"})
assert.Equal(t, []any{uint64(1), nil}, tup)

In summary, the package provides flexible capabilities for creating type converters.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.