{-# 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