    {-# LANGUAGE FlexibleInstances #-}
    {-# OPTIONS_GHC -fno-warn-orphans #-}

    module Data.Configurator.Instances () where

    import Control.Applicative
    import Data.Configurator.Types.Internal
    import Data.Complex (Complex)
    import Data.Fixed (Fixed, HasResolution)
    import Data.Int (Int8, Int16, Int32, Int64)
    import Data.Text.Encoding (encodeUtf8)
    import Data.Ratio (Ratio, denominator, numerator)
    import Data.Word (Word, Word8, Word16, Word32, Word64)
    import Foreign.C.Types (CDouble, CFloat)
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Lazy as LB
    import qualified Data.Text as T
    import qualified Data.Text.Lazy as L

    instance Configured Value where
        convert :: Value -> Maybe Value
    convert = Value -> Maybe Value
    forall a. a -> Maybe a
    Just

    instance Configured Bool where
        convert :: Value -> Maybe Bool
    convert (Bool Bool
    v) = Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    v
        convert Value
    _        = Maybe Bool
    forall a. Maybe a
    Nothing

    convertNumberToNum :: (Num a) => Value -> Maybe a
    convertNumberToNum :: forall a. Num a => Value -> Maybe a
    convertNumberToNum (Number Rational
    r)
        | Rational -> Integer
    forall a. Ratio a -> a
    denominator Rational
    r Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer
    1 = a -> Maybe a
    forall a. a -> Maybe a
    Just (a -> Maybe a) -> a -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ Integer -> a
    forall a. Num a => Integer -> a
    fromInteger (Integer -> a) -> Integer -> a
    forall a b. (a -> b) -> a -> b
    $ Rational -> Integer
    forall a. Ratio a -> a
    numerator Rational
    r
    convertNumberToNum Value
    _ = Maybe a
    forall a. Maybe a
    Nothing

    instance Configured Int where
        convert :: Value -> Maybe Int
    convert = Value -> Maybe Int
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Integer where
        convert :: Value -> Maybe Integer
    convert = Value -> Maybe Integer
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Int8 where
        convert :: Value -> Maybe Int8
    convert = Value -> Maybe Int8
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Int16 where
        convert :: Value -> Maybe Int16
    convert = Value -> Maybe Int16
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Int32 where
        convert :: Value -> Maybe Int32
    convert = Value -> Maybe Int32
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Int64 where
        convert :: Value -> Maybe Int64
    convert = Value -> Maybe Int64
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Word where
        convert :: Value -> Maybe Word
    convert = Value -> Maybe Word
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Word8 where
        convert :: Value -> Maybe Word8
    convert = Value -> Maybe Word8
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Word16 where
        convert :: Value -> Maybe Word16
    convert = Value -> Maybe Word16
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Word32 where
        convert :: Value -> Maybe Word32
    convert = Value -> Maybe Word32
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    instance Configured Word64 where
        convert :: Value -> Maybe Word64
    convert = Value -> Maybe Word64
    forall a. Num a => Value -> Maybe a
    convertNumberToNum

    convertNumberToFractional :: (Fractional a) => Value -> Maybe a
    convertNumberToFractional :: forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional (Number Rational
    r) = a -> Maybe a
    forall a. a -> Maybe a
    Just (a -> Maybe a) -> a -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ Rational -> a
    forall a. Fractional a => Rational -> a
    fromRational Rational
    r
    convertNumberToFractional Value
    _ = Maybe a
    forall a. Maybe a
    Nothing

    instance Configured Double where
        convert :: Value -> Maybe Double
    convert = Value -> Maybe Double
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance Configured Float where
        convert :: Value -> Maybe Float
    convert = Value -> Maybe Float
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance Configured CDouble where
        convert :: Value -> Maybe CDouble
    convert = Value -> Maybe CDouble
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance Configured CFloat where
        convert :: Value -> Maybe CFloat
    convert = Value -> Maybe CFloat
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance Integral a => Configured (Ratio a) where
        convert :: Value -> Maybe (Ratio a)
    convert = Value -> Maybe (Ratio a)
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance RealFloat a => Configured (Complex a) where
        convert :: Value -> Maybe (Complex a)
    convert = Value -> Maybe (Complex a)
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance HasResolution a => Configured (Fixed a) where
        convert :: Value -> Maybe (Fixed a)
    convert = Value -> Maybe (Fixed a)
    forall a. Fractional a => Value -> Maybe a
    convertNumberToFractional

    instance Configured T.Text where
        convert :: Value -> Maybe Text
    convert (String Text
    v) = Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    v
        convert Value
    _          = Maybe Text
    forall a. Maybe a
    Nothing

    instance Configured Char where
        convert :: Value -> Maybe Char
    convert (String Text
    txt) | Text -> Int
    T.length Text
    txt Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    1 = Char -> Maybe Char
    forall a. a -> Maybe a
    Just (Char -> Maybe Char) -> Char -> Maybe Char
    forall a b. (a -> b) -> a -> b
    $ HasCallStack => Text -> Char
    Text -> Char
    T.head Text
    txt
        convert Value
    _ = Maybe Char
    forall a. Maybe a
    Nothing

        convertList :: Value -> Maybe [Char]
    convertList = (Text -> [Char]) -> Maybe Text -> Maybe [Char]
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Text -> [Char]
    T.unpack (Maybe Text -> Maybe [Char])
    -> (Value -> Maybe Text) -> Value -> Maybe [Char]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Maybe Text
    forall a. Configured a => Value -> Maybe a
    convert

    instance Configured L.Text where
        convert :: Value -> Maybe Text
    convert = (Text -> Text) -> Maybe Text -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Text -> Text
    L.fromStrict (Maybe Text -> Maybe Text)
    -> (Value -> Maybe Text) -> Value -> Maybe Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Maybe Text
    forall a. Configured a => Value -> Maybe a
    convert

    instance Configured B.ByteString where
        convert :: Value -> Maybe ByteString
    convert = (Text -> ByteString) -> Maybe Text -> Maybe ByteString
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Text -> ByteString
    encodeUtf8 (Maybe Text -> Maybe ByteString)
    -> (Value -> Maybe Text) -> Value -> Maybe ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Maybe Text
    forall a. Configured a => Value -> Maybe a
    convert

    instance Configured LB.ByteString where
        convert :: Value -> Maybe ByteString
    convert = (ByteString -> ByteString) -> Maybe ByteString -> Maybe ByteString
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([ByteString] -> ByteString
    LB.fromChunks ([ByteString] -> ByteString)
    -> (ByteString -> [ByteString]) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    :[])) (Maybe ByteString -> Maybe ByteString)
    -> (Value -> Maybe ByteString) -> Value -> Maybe ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> Maybe ByteString
    forall a. Configured a => Value -> Maybe a
    convert

    instance (Configured a, Configured b) => Configured (a,b) where
        convert :: Value -> Maybe (a, b)
    convert (List [Value
    a,Value
    b]) = (,) (a -> b -> (a, b)) -> Maybe a -> Maybe (b -> (a, b))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Value -> Maybe a
    forall a. Configured a => Value -> Maybe a
    convert Value
    a Maybe (b -> (a, b)) -> Maybe b -> Maybe (a, b)
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Value -> Maybe b
    forall a. Configured a => Value -> Maybe a
    convert Value
    b
        convert Value
    _            = Maybe (a, b)
    forall a. Maybe a
    Nothing

    instance (Configured a, Configured b, Configured c) => Configured (a,b,c) where
        convert :: Value -> Maybe (a, b, c)
    convert (List [Value
    a,Value
    b,Value
    c]) = (,,) (a -> b -> c -> (a, b, c))
    -> Maybe a -> Maybe (b -> c -> (a, b, c))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Value -> Maybe a
    forall a. Configured a => Value -> Maybe a
    convert Value
    a Maybe (b -> c -> (a, b, c)) -> Maybe b -> Maybe (c -> (a, b, c))
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Value -> Maybe b
    forall a. Configured a => Value -> Maybe a
    convert Value
    b Maybe (c -> (a, b, c)) -> Maybe c -> Maybe (a, b, c)
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Value -> Maybe c
    forall a. Configured a => Value -> Maybe a
    convert Value
    c
        convert Value
    _              = Maybe (a, b, c)
    forall a. Maybe a
    Nothing

    instance (Configured a, Configured b, Configured c, Configured d)
        => Configured (a,b,c,d) where
        convert :: Value -> Maybe (a, b, c, d)
    convert (List [Value
    a,Value
    b,Value
    c,Value
    d]) = (,,,) (a -> b -> c -> d -> (a, b, c, d))
    -> Maybe a -> Maybe (b -> c -> d -> (a, b, c, d))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Value -> Maybe a
    forall a. Configured a => Value -> Maybe a
    convert Value
    a Maybe (b -> c -> d -> (a, b, c, d))
    -> Maybe b -> Maybe (c -> d -> (a, b, c, d))
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Value -> Maybe b
    forall a. Configured a => Value -> Maybe a
    convert Value
    b Maybe (c -> d -> (a, b, c, d))
    -> Maybe c -> Maybe (d -> (a, b, c, d))
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Value -> Maybe c
    forall a. Configured a => Value -> Maybe a
    convert Value
    c
                                         Maybe (d -> (a, b, c, d)) -> Maybe d -> Maybe (a, b, c, d)
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Value -> Maybe d
    forall a. Configured a => Value -> Maybe a
    convert Value
    d
        convert Value
    _                = Maybe (a, b, c, d)
    forall a. Maybe a
    Nothing