{-# Language TypeFamilies #-}
module Toml.FromValue (
    
    FromValue(..),
    FromKey(..),
    
    Matcher,
    MatchMessage(..),
    Result(..),
    warning,
    
    ParseTable,
    runParseTable,
    parseTableFromValue,
    reqKey,
    optKey,
    reqKeyOf,
    optKeyOf,
    warnTable,
    KeyAlt(..),
    pickKey,
    
    getTable,
    setTable,
    liftMatcher,
    ) where
import Control.Monad (zipWithM)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.List.NonEmpty (NonEmpty)
import Data.List.NonEmpty qualified as NonEmpty
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Ratio (Ratio)
import Data.Sequence (Seq)
import Data.Sequence qualified as Seq
import Data.String (IsString (fromString))
import Data.Text qualified
import Data.Text.Lazy qualified
import Data.Time (ZonedTime, LocalTime, Day, TimeOfDay)
import Data.Word (Word8, Word16, Word32, Word64)
import Numeric.Natural (Natural)
import Toml.FromValue.Matcher (Matcher, Result(..), MatchMessage(..), warning, inIndex, inKey)
import Toml.FromValue.ParseTable
import Toml.Value (Value(..))
class FromValue a where
    
    fromValue :: Value -> Matcher a
    
    listFromValue :: Value -> Matcher [a]
    listFromValue (Array [Value]
xs) = forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (\Int
i Value
v -> forall a. Int -> Matcher a -> Matcher a
inIndex Int
i (forall a. FromValue a => Value -> Matcher a
fromValue Value
v)) [Int
0..] [Value]
xs
    listFromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"array" Value
v
instance (Ord k, FromKey k, FromValue v) => FromValue (Map k v) where
    fromValue :: Value -> Matcher (Map k v)
fromValue (Table Table
t) = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall {a} {a}.
(FromKey a, FromValue a) =>
(String, Value) -> Matcher (a, a)
f (forall k a. Map k a -> [(k, a)]
Map.assocs Table
t)
        where
            f :: (String, Value) -> Matcher (a, a)
f (String
k,Value
v) = (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromKey a => String -> Matcher a
fromKey String
k forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. String -> Matcher a -> Matcher a
inKey String
k (forall a. FromValue a => Value -> Matcher a
fromValue Value
v)
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"table" Value
v
class FromKey a where
    fromKey :: String -> Matcher a
instance a ~ Char => FromKey [a] where
    fromKey :: String -> Matcher [a]
fromKey = forall (f :: * -> *) a. Applicative f => a -> f a
pure
instance FromKey Data.Text.Text where
    fromKey :: String -> Matcher Text
fromKey = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Data.Text.pack
instance FromKey Data.Text.Lazy.Text where
    fromKey :: String -> Matcher Text
fromKey = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Data.Text.Lazy.pack
typeError :: String  -> Value  -> Matcher a
typeError :: forall a. String -> Value -> Matcher a
typeError String
wanted Value
got = forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"type error. wanted: " forall a. [a] -> [a] -> [a]
++ String
wanted forall a. [a] -> [a] -> [a]
++ String
" got: " forall a. [a] -> [a] -> [a]
++ Value -> String
valueType Value
got)
parseTableFromValue :: ParseTable a -> Value -> Matcher a
parseTableFromValue :: forall a. ParseTable a -> Value -> Matcher a
parseTableFromValue ParseTable a
p (Table Table
t) = forall a. ParseTable a -> Table -> Matcher a
runParseTable ParseTable a
p Table
t
parseTableFromValue ParseTable a
_ Value
v = forall a. String -> Value -> Matcher a
typeError String
"table" Value
v
valueType :: Value -> String
valueType :: Value -> String
valueType = \case
    Integer   {} -> String
"integer"
    Float     {} -> String
"float"
    Array     {} -> String
"array"
    Table     {} -> String
"table"
    Bool      {} -> String
"boolean"
    String    {} -> String
"string"
    TimeOfDay {} -> String
"local time"
    LocalTime {} -> String
"local date-time"
    Day       {} -> String
"locate date"
    ZonedTime {} -> String
"offset date-time"
instance FromValue Integer where
    fromValue :: Value -> Matcher Integer
fromValue (Integer Integer
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure Integer
x
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"integer" Value
v
instance FromValue Natural where
    fromValue :: Value -> Matcher Natural
fromValue Value
v =
     do Integer
i <- forall a. FromValue a => Value -> Matcher a
fromValue Value
v
        if Integer
0 forall a. Ord a => a -> a -> Bool
<= Integer
i then
            forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Num a => Integer -> a
fromInteger Integer
i)
        else
            forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"integer out of range for Natural"
fromValueSized :: forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized :: forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
name Value
v =
 do Integer
i <- forall a. FromValue a => Value -> Matcher a
fromValue Value
v
    if forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound :: a) forall a. Ord a => a -> a -> Bool
<= Integer
i Bool -> Bool -> Bool
&& Integer
i forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound :: a) then
        forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Num a => Integer -> a
fromInteger Integer
i)
    else
        forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"integer out of range for " forall a. [a] -> [a] -> [a]
++ String
name)
instance FromValue Int    where fromValue :: Value -> Matcher Int
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Int"
instance FromValue Int8   where fromValue :: Value -> Matcher Int8
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Int8"
instance FromValue Int16  where fromValue :: Value -> Matcher Int16
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Int16"
instance FromValue Int32  where fromValue :: Value -> Matcher Int32
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Int32"
instance FromValue Int64  where fromValue :: Value -> Matcher Int64
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Int64"
instance FromValue Word   where fromValue :: Value -> Matcher Word
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Word"
instance FromValue Word8  where fromValue :: Value -> Matcher Word8
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Word8"
instance FromValue Word16 where fromValue :: Value -> Matcher Word16
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Word16"
instance FromValue Word32 where fromValue :: Value -> Matcher Word32
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Word32"
instance FromValue Word64 where fromValue :: Value -> Matcher Word64
fromValue = forall a. (Bounded a, Integral a) => String -> Value -> Matcher a
fromValueSized String
"Word64"
instance FromValue Char where
    fromValue :: Value -> Matcher Char
fromValue (String [Char
c]) = forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
c
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"character" Value
v
    listFromValue :: Value -> Matcher String
listFromValue (String String
xs) = forall (f :: * -> *) a. Applicative f => a -> f a
pure String
xs
    listFromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"string" Value
v
instance FromValue Data.Text.Text where
    fromValue :: Value -> Matcher Text
fromValue Value
v = String -> Text
Data.Text.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromValue a => Value -> Matcher a
fromValue Value
v
instance FromValue Data.Text.Lazy.Text where
    fromValue :: Value -> Matcher Text
fromValue Value
v = String -> Text
Data.Text.Lazy.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromValue a => Value -> Matcher a
fromValue Value
v
instance FromValue Double where
    fromValue :: Value -> Matcher Double
fromValue (Float Double
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure Double
x
    fromValue (Integer Integer
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Num a => Integer -> a
fromInteger Integer
x)
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"float" Value
v
instance FromValue Float where
    fromValue :: Value -> Matcher Float
fromValue (Float Double
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. (Real a, Fractional b) => a -> b
realToFrac Double
x)
    fromValue (Integer Integer
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Num a => Integer -> a
fromInteger Integer
x)
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"float" Value
v
instance Integral a => FromValue (Ratio a) where
    fromValue :: Value -> Matcher (Ratio a)
fromValue (Float Double
x)
        | forall a. RealFloat a => a -> Bool
isNaN Double
x Bool -> Bool -> Bool
|| forall a. RealFloat a => a -> Bool
isInfinite Double
x = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"finite float required"
        | Bool
otherwise = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. (Real a, Fractional b) => a -> b
realToFrac Double
x)
    fromValue (Integer Integer
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Num a => Integer -> a
fromInteger Integer
x)
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"float" Value
v
instance FromValue a => FromValue (NonEmpty a) where
    fromValue :: Value -> Matcher (NonEmpty a)
fromValue Value
v =
     do [a]
xs <- forall a. FromValue a => Value -> Matcher a
fromValue Value
v
        case forall a. [a] -> Maybe (NonEmpty a)
NonEmpty.nonEmpty [a]
xs of
            Maybe (NonEmpty a)
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"non-empty list required"
            Just NonEmpty a
ne -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NonEmpty a
ne
instance FromValue a => FromValue (Seq a) where
    fromValue :: Value -> Matcher (Seq a)
fromValue Value
v = forall a. [a] -> Seq a
Seq.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromValue a => Value -> Matcher a
fromValue Value
v
instance FromValue Bool where
    fromValue :: Value -> Matcher Bool
fromValue (Bool Bool
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
x
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"boolean" Value
v
instance FromValue a => FromValue [a] where
    fromValue :: Value -> Matcher [a]
fromValue = forall a. FromValue a => Value -> Matcher [a]
listFromValue
instance FromValue Day where
    fromValue :: Value -> Matcher Day
fromValue (Day Day
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure Day
x
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"local date" Value
v
instance FromValue TimeOfDay where
    fromValue :: Value -> Matcher TimeOfDay
fromValue (TimeOfDay TimeOfDay
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure TimeOfDay
x
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"local time" Value
v
instance FromValue ZonedTime where
    fromValue :: Value -> Matcher ZonedTime
fromValue (ZonedTime ZonedTime
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure ZonedTime
x
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"offset date-time" Value
v
instance FromValue LocalTime where
    fromValue :: Value -> Matcher LocalTime
fromValue (LocalTime LocalTime
x) = forall (f :: * -> *) a. Applicative f => a -> f a
pure LocalTime
x
    fromValue Value
v = forall a. String -> Value -> Matcher a
typeError String
"local date-time" Value
v
instance FromValue Value where
    fromValue :: Value -> Matcher Value
fromValue = forall (f :: * -> *) a. Applicative f => a -> f a
pure
optKey :: FromValue a => String -> ParseTable (Maybe a)
optKey :: forall a. FromValue a => String -> ParseTable (Maybe a)
optKey String
key = forall a. String -> (Value -> Matcher a) -> ParseTable (Maybe a)
optKeyOf String
key forall a. FromValue a => Value -> Matcher a
fromValue
reqKey :: FromValue a => String -> ParseTable a
reqKey :: forall a. FromValue a => String -> ParseTable a
reqKey String
key = forall a. String -> (Value -> Matcher a) -> ParseTable a
reqKeyOf String
key forall a. FromValue a => Value -> Matcher a
fromValue
optKeyOf ::
    String  ->
    (Value -> Matcher a)  ->
    ParseTable (Maybe a)
optKeyOf :: forall a. String -> (Value -> Matcher a) -> ParseTable (Maybe a)
optKeyOf String
key Value -> Matcher a
k = forall a. [KeyAlt a] -> ParseTable a
pickKey [forall a. String -> (Value -> Matcher a) -> KeyAlt a
Key String
key (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Matcher a
k), forall a. Matcher a -> KeyAlt a
Else (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing)]
reqKeyOf ::
    String  ->
    (Value -> Matcher a)  ->
    ParseTable a
reqKeyOf :: forall a. String -> (Value -> Matcher a) -> ParseTable a
reqKeyOf String
key Value -> Matcher a
k = forall a. [KeyAlt a] -> ParseTable a
pickKey [forall a. String -> (Value -> Matcher a) -> KeyAlt a
Key String
key Value -> Matcher a
k]