-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
185 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,185 @@ | ||
# Parser in Go for Tarantool types | ||
# Tarantool tuples converter in Go | ||
## Table of contents | ||
* [Documentation](#documentation) | ||
* [Mapper](#mapper) | ||
* [Converter](#converter) | ||
* [Convert to tarantool types](#convert-to-tarantool-types) | ||
* [Example](#example) | ||
* [String to nullable](#string-to-nullable) | ||
* [String to any/scalar](#string-to-anyscalar) | ||
* [Customization](#customization) | ||
## Documentation | ||
|
||
### Mapper | ||
`Mapper[S,T]` maps objects of type `S` into objects of type `T`. Mappers are | ||
basic entities on which converters are based. | ||
Implementations of some mappers are available, for example, mappers from strings | ||
to go types. | ||
Usage example: | ||
```golang | ||
// Basic mapper. | ||
mapper := tupleconv.MakeStringToBoolMapper() | ||
result, err := mapper.Map("true") // true <nil> | ||
|
||
// Function based mapper. | ||
fMapper := tupleconv.MakeFuncMapper(func(s string) (string, error) { | ||
return s + " world!", nil | ||
}) | ||
result, err = fMapper.Map("hello") // hello world! <nil> | ||
``` | ||
**Observation 1**: You can use the provided mappers for type conversion, | ||
please make sure to specify the input format they expect before using them. | ||
Examples of supported formats are described in the [tests](mapper_test.go). | ||
|
||
**Observation 2**: You can create your own mappers based on the functions with | ||
`tupleconv.MakeFuncMapper`. | ||
|
||
**Observation 3**: You can create your own mappers, implementing `Mapper[S,T]` | ||
interface. | ||
|
||
### Converter | ||
`Converter` is an object that converts tuples. It is built using a list of | ||
mappers. | ||
Usage example: | ||
```golang | ||
// Converter example. | ||
customConverter := tupleconv.NewConverter[string, any]([]tupleconv.Mapper[string, any]{ | ||
tupleconv.MakeFuncMapper(func(s string) (any, error) { | ||
return s + "1", nil | ||
}), | ||
tupleconv.MakeFuncMapper(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 := customConverter.Convert([]string{"a", "4"}) // []any{"a1", 5} <nil> | ||
|
||
result, err = customConverter.ConvertWithErrHandler([]string{"a", "b"}, func(i int, err error) (any, error) { | ||
return "null", nil | ||
}) // []any{"a1", "null"} <nil> | ||
``` | ||
```golang | ||
// Single converter example. | ||
toStringConverter := tupleconv.NewConverterSingle[any, string](tupleconv.MakeFuncMapper( | ||
func(s any) (string, error) { | ||
return fmt.Sprintln(s), nil | ||
}), | ||
) | ||
res, err := toStringConverter.Convert([]any{1, 2.5, nil}) // ["1\n", "2.5\n", "<nil>\n"] <nil> | ||
``` | ||
**Observation 1**: To create a converter, an array of mappers is needed, each | ||
of which transforms a certain type S into type T. | ||
|
||
**Observation 2**: To perform tuple conversion, you can use the function | ||
`Convert`, which will return control to the calling code upon the first error. | ||
|
||
**Observation 3**: To perform tuple conversion, you can use the function | ||
`ConvertWithErrHandler`. Upon a conversion error, it will call the function | ||
provided as the second argument, referred to as the Error Handler. | ||
It will pass the index where the error occurred and the error itself to the | ||
Error Handler. The Error Handler can return a new value for that index or | ||
return an error again to halt the execution of the function at that point. | ||
|
||
**Observation 4**: You can use a single mapper to create a converter. | ||
This converter is created by the function `NewConverterSingle`, and its | ||
`Convert` function will work like a `map` function in some programming languages. | ||
|
||
### Convert to tarantool types | ||
|
||
#### Example | ||
For building an array of mappers, especially when it comes to conversions to | ||
Tarantool types, there is a built-in solution. | ||
Let's consider an example: | ||
```golang | ||
package main | ||
|
||
import "github.com/tarantool/go-tupleconv" | ||
|
||
func main() { | ||
factory := tupleconv.NewStringToTTMapperFactory() | ||
factory.Cfg(tupleconv.StringToTTMapperOpts{ | ||
DecSeparators: ",.", | ||
}) | ||
|
||
spaceFmt := []tarantool.Field{ | ||
{Type: "unsigned"}, | ||
{Type: "double", IsNullable: true}, | ||
{Type: "string"}, | ||
} | ||
|
||
mappers, err := tupleconv.MakeTypeToTTMapperList[string](factory, spaceFmt) | ||
converter := tupleconv.NewConverter(mappers) | ||
converter.Convert([]string{"1", "-2,2", "some_string"}) // [1, -2.2, "some_string"] <nil> | ||
} | ||
``` | ||
**Observation 1**: To build an array of mappers, the space format and a certain | ||
object called `TypeToTTMapperFactory` are used. Function | ||
`MakeTypeToTTMapperList` takes these entities and gives the mappers list. | ||
|
||
**Observation 2**: `TypeToTTMapperFactory[Type]` is capable of building a mapper | ||
from type `Type` to each Tarantool type. | ||
|
||
**Observation 3**: There is a basic factory available called | ||
`StringToTTMapperFactory`, which is used for conversions from strings to | ||
Tarantool types. | ||
|
||
**Observation 4**: `StringToTTMapperFactory` can be configured with `Cfg`. | ||
|
||
#### String to nullable | ||
When converting nullable types with `StringToTTMapperFactory`, an attempt will | ||
be made to convert them to the base type. | ||
|
||
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 an empty string during the conversion process, rather than being | ||
converted to null. | ||
|
||
|
||
#### String to any/scalar | ||
When converting to `any`/`scalar` with `StringToTTMapperFactory`, 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 | ||
`TypeToTTMapperFactory[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 mappers from strings to | ||
Tarantool types always convert `any` type to a string: | ||
```golang | ||
package main | ||
|
||
import ( | ||
"github.com/tarantool/go-tarantool/v2" | ||
"github.com/tarantool/go-tupleconv" | ||
) | ||
|
||
type customFacture struct { | ||
tupleconv.StringToTTMapperFactory | ||
} | ||
|
||
func (f *customFacture) MakeTypeToAnyMapper() tupleconv.Mapper[string, any] { | ||
return tupleconv.MakeFuncMapper(func(s string) (any, error) { | ||
return s, nil | ||
}) | ||
} | ||
|
||
func main() { | ||
facture := &customFacture{} | ||
spaceFmt := []tarantool.Field{{Type: "any"}} | ||
mappers, _ := tupleconv.MakeTypeToTTMapperList[string](facture, spaceFmt) | ||
|
||
res, err := mappers[0].Map("12") // "12" <nil> | ||
} | ||
``` |