tomland-1.3.3.3: Bidirectional TOML serialization
Copyright(c) 2018-2022 Kowainik
LicenseMPL-2.0
MaintainerKowainik <xrom.xkov@gmail.com>
StabilityStable
PortabilityPortable
Safe HaskellSafe-Inferred
LanguageHaskell2010

Toml.Codec.Combinator.Custom

Description

Contains TOML-specific custom combinators for converting between TOML and special user data types.

See examples below of the situations you may need the following combinators.

Since: 1.3.0.0

Synopsis

Text combinators

textBy :: (a -> Text) -> (Text -> Either Text a) -> Key -> TomlCodec a Source #

Codec for text values with custom error messages for parsing.

Example:

We have the following type that represents the image format:

data Format
    = Jpeg
    | Png
    | Gif
    deriving (Show, Read, Enum)

But we want to be able to decode and encode this data type through the custom text representation, that can be formilised in the following functions:

showFormat :: Format -> Text
showFormat = case
    Jpeg -> ".jpeg"
    Png  -> ".png"
    Gif  -> ".gif"

parseFormat :: Text -> Either Text Format
parseFormat = case
    ".jpeg" -> Right Jpeg
    ".png"  -> Right Png
    ".gif"  -> Right Gif
    other   -> Left $ "Unsupported format: " <> other

To write the codec for Format data type using the above rules we can use textBy combinator:

formatCodec :: Key -> TomlCodec Format
formatCodec = textBy showFormat parseFormat

And now with the formatCodec "foo" we can have the following line in our TOML perfectly encoded:

foo = ".gif"

But the foo = "jif" will lead to the following error:

tomland decode error:  Unsupported format: jif

Since: 1.0.0

read :: (Show a, Read a) => Key -> TomlCodec a Source #

Codec for values with a Read and Show instance.

Example:

We have the following type that represents the image format:

data Format
    = Jpeg
    | Png
    | Gif
    deriving (Show, Read, Enum)

And we want to be able to decode and encode this data type through the Show and Read instances.

To write the codec for Format data type using the existing instances we can use read combinator. And now with the Toml.read "foo" we can have the following line in our TOML perfectly encoded:

foo = Gif

But the foo = ".gif" will lead to the following error:

tomland decode error:  Prelude.read: no parse

Since: 0.5.0

enumBounded :: (Bounded a, Enum a, Show a) => Key -> TomlCodec a Source #

Codec for general nullary sum data types with a Bounded, Enum, and Show instance. This codec is similar to read but provides much better error messages than read for nullary sum types.

E.g. for the same Format example from read function, but with the Toml.enumBounded "foo" codec the error for foo = "Jif" in the TOML file will look like this:

tomland decode error:  Value is Jif but expected one of: Jpeg, Png, Gif

Since: 1.1.0.0

hardcoded :: (Show a, Eq a) => a -> TomlBiMap a AnyValue -> Key -> TomlCodec a Source #

Codec for hardcoded provided values and its BiMap.

If you want to decode a single key-value pair where only one value is allowed. Like in the example below:

scope = "all"

To decode that you could use the following function:

Toml.hardcoded "all" Toml._Text "scope"

in case if the value in TOML is not the same as hardcoded, you will get the following error:

tomland decode error:  BiMap error in key scope : Value '"foo"' doesn't align with the hardcoded value '"all"'

Since: 1.3.2.0

Validation

validate :: (a -> Either Text a) -> TomlBiMap a AnyValue -> Key -> TomlCodec a Source #

Codec that checks the BiMap on the given predicate. The predicate function returns the value, if the validation is successful, or the Text of the error that should be returned in case of validation failure.

Example:

Let's imagine that we want to have the list in TOML that could only have even Ints inside. In this case, you can write the following codec:

allEven :: [Int] -> Either Text [Int]
allEven xs =
    if all even xs
    then Right xs
    else Left "This is wrong, I asked you for even only :("

allEvenCodec :: TomlCodec [Int]
allEvenCodec = Toml.validate allEven (Toml._Array Toml._Int) "myEvenList"

Then in your TOML file you can have:

myEvenList = [2, 4, 6]

But the following one will lead to the error:

myEvenList = [1, 2, 3]
tomland decode error:  This is wrong, I asked you for even only :(

Since: 1.3.0.0

validateIf :: forall a. (a -> Bool) -> TomlBiMap a AnyValue -> Key -> TomlCodec a Source #

Similar to validate but takes the predicate that returnes Bool. The error in case of the validation failure looks like this:

Value does not pass the validation for key: KEY_NAME

Example:

Let's imagine that we want to have the Text field in TOML that could only have 3 chars in it. In this case, you can write the following codec:

my3charTextCodec :: TomlCodec Text
my3CharTextCodec = Toml.validateIf ((==) 3 . Text.length) Toml._Text "myKeyName"

The in your TOML file you can have:

myKeyName = "abc"

But the following one will lead to the error:

myKeyName = "I have more than enough"
tomland decode error:  Value does not pass the validation for key: myKeyName

Since: 1.3.0.0