{-# LANGUAGE KindSignatures, DataKinds #-}
{-# LANGUAGE UndecidableInstances, FlexibleContexts #-}
{-# LANGUAGE PolyKinds #-}
module Data.Ron.Class.Deriving
( RonWith (..)
, UseStrict
, EncodeWith
, DecodeWith
, ConvertWith
, FieldsToSnakeCase
, FieldsDropPrefix
, ImplicitSome
, NoImplicitSome
, SkipSingleConstructor
, NoSkipSingleConstructor
, ReflectSettingsOptions (..)
, ReflectFlagOptions (..)
) where
import Data.Char (isUpper, toLower, isLower)
import Data.Proxy (Proxy (..))
import GHC.Generics (Generic, Rep)
import Data.Ron.Class
newtype RonWith s a = RonWith a
instance (Generic a, GToRon (Rep a), ReflectSettingsList s)
=> ToRon (RonWith s a) where
toRon :: RonWith s a -> Value
toRon (RonWith a
x) = (RonSettings -> a -> Value) -> a -> RonSettings -> Value
forall a b c. (a -> b -> c) -> b -> a -> c
flip RonSettings -> a -> Value
forall a. (Generic a, GToRon (Rep a)) => RonSettings -> a -> Value
toRonGeneric a
x (RonSettings -> Value) -> RonSettings -> Value
forall a b. (a -> b) -> a -> b
$ Proxy s -> RonSettings -> RonSettings
forall {k} (a :: k).
ReflectSettingsList a =>
Proxy a -> RonSettings -> RonSettings
reflectL (forall (t :: k). Proxy t
forall {k} (t :: k). Proxy t
Proxy @s) RonSettings
laxRonSettings
instance (Generic a, GFromRon (Rep a), ReflectSettingsList s)
=> FromRon (RonWith s a) where
fromRon :: Value -> ParseResult (RonWith s a)
fromRon = (a -> RonWith s a) -> Either String a -> ParseResult (RonWith s a)
forall a b. (a -> b) -> Either String a -> Either String b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> RonWith s a
forall {k} (s :: k) a. a -> RonWith s a
RonWith (Either String a -> ParseResult (RonWith s a))
-> (Value -> Either String a) -> Value -> ParseResult (RonWith s a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RonSettings -> Value -> Either String a
forall a.
(Generic a, GFromRon (Rep a)) =>
RonSettings -> Value -> ParseResult a
fromRonGeneric (Proxy s -> RonSettings -> RonSettings
forall {k} (a :: k).
ReflectSettingsList a =>
Proxy a -> RonSettings -> RonSettings
reflectL (forall (t :: k). Proxy t
forall {k} (t :: k). Proxy t
Proxy @s) RonSettings
laxRonSettings)
class ReflectSettingsList a where
reflectL :: Proxy a -> RonSettings -> RonSettings
instance ReflectSettingsList '[] where
reflectL :: Proxy '[] -> RonSettings -> RonSettings
reflectL Proxy '[]
Proxy RonSettings
s = RonSettings
s
{-# INLINE reflectL #-}
instance (ReflectSettingsOptions s, ReflectSettingsList ss)
=> ReflectSettingsList (s:ss) where
reflectL :: Proxy (s : ss) -> RonSettings -> RonSettings
reflectL Proxy (s : ss)
Proxy
= Proxy ss -> RonSettings -> RonSettings
forall {k} (a :: k).
ReflectSettingsList a =>
Proxy a -> RonSettings -> RonSettings
reflectL (forall (t :: [a]). Proxy t
forall {k} (t :: k). Proxy t
Proxy @ss)
(RonSettings -> RonSettings)
-> (RonSettings -> RonSettings) -> RonSettings -> RonSettings
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy s -> RonSettings -> RonSettings
forall {k} (a :: k).
ReflectSettingsOptions a =>
Proxy a -> RonSettings -> RonSettings
reflectS (forall (t :: a). Proxy t
forall {k} (t :: k). Proxy t
Proxy @s)
{-# INLINE reflectL #-}
data UseStrict
data EncodeWith a
data DecodeWith a
data ConvertWith a
data FieldsToSnakeCase
data FieldsDropPrefix
class ReflectSettingsOptions a where
reflectS :: Proxy a -> RonSettings -> RonSettings
data ImplicitSome
data NoImplicitSome
data SkipSingleConstructor
data NoSkipSingleConstructor
class ReflectFlagOptions a where
reflectF :: Proxy a -> RonFlags -> RonFlags
instance ReflectSettingsOptions UseStrict where
reflectS :: Proxy UseStrict -> RonSettings -> RonSettings
reflectS Proxy UseStrict
Proxy RonSettings
_ = RonSettings
strictRonSettings
{-# INLINE reflectS #-}
instance ReflectFlagOptions a => ReflectSettingsOptions (EncodeWith a) where
reflectS :: Proxy (EncodeWith a) -> RonSettings -> RonSettings
reflectS Proxy (EncodeWith a)
Proxy s :: RonSettings
s@RonSettings {RonFlags
encodeFlags :: RonFlags
encodeFlags :: RonSettings -> RonFlags
encodeFlags} = RonSettings
s
{ encodeFlags = reflectF (Proxy @a) encodeFlags }
{-# INLINE reflectS #-}
instance ReflectFlagOptions a => ReflectSettingsOptions (DecodeWith a) where
reflectS :: Proxy (DecodeWith a) -> RonSettings -> RonSettings
reflectS Proxy (DecodeWith a)
Proxy s :: RonSettings
s@RonSettings {RonFlags
decodeFlags :: RonFlags
decodeFlags :: RonSettings -> RonFlags
decodeFlags} = RonSettings
s
{ decodeFlags = reflectF (Proxy @a) decodeFlags }
{-# INLINE reflectS #-}
instance ReflectFlagOptions a => ReflectSettingsOptions (ConvertWith a) where
reflectS :: Proxy (ConvertWith a) -> RonSettings -> RonSettings
reflectS Proxy (ConvertWith a)
Proxy s :: RonSettings
s@RonSettings {RonFlags
encodeFlags :: RonSettings -> RonFlags
encodeFlags :: RonFlags
encodeFlags, RonFlags
decodeFlags :: RonSettings -> RonFlags
decodeFlags :: RonFlags
decodeFlags} = RonSettings
s
{ encodeFlags = reflectF (Proxy @a) encodeFlags
, decodeFlags = reflectF (Proxy @a) decodeFlags
}
{-# INLINE reflectS #-}
instance ReflectSettingsOptions FieldsDropPrefix where
reflectS :: Proxy FieldsDropPrefix -> RonSettings -> RonSettings
reflectS Proxy FieldsDropPrefix
Proxy conf :: RonSettings
conf@RonSettings {String -> String
fieldModifier :: String -> String
fieldModifier :: RonSettings -> String -> String
fieldModifier} = RonSettings
conf
{ fieldModifier = dropPrefix . fieldModifier }
where
dropPrefix :: String -> String
dropPrefix (Char
'_':String
s) =
case (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isUpper) String
s of
String
"" -> Char
'_'Char -> String -> String
forall a. a -> [a] -> [a]
:String
s
Char
c:String
s' -> Char -> Char
toLower Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
s'
dropPrefix String
s = String
s
{-# INLINE reflectS #-}
instance ReflectSettingsOptions FieldsToSnakeCase where
reflectS :: Proxy FieldsToSnakeCase -> RonSettings -> RonSettings
reflectS Proxy FieldsToSnakeCase
Proxy s :: RonSettings
s@RonSettings {String -> String
fieldModifier :: RonSettings -> String -> String
fieldModifier :: String -> String
fieldModifier} = RonSettings
s
{ fieldModifier = toSnake . fieldModifier }
where
toSnake :: String -> String
toSnake = Char -> String -> String
camelTo2 Char
'_'
{-# INLINE reflectS #-}
camelTo2 :: Char -> String -> String
camelTo2 :: Char -> String -> String
camelTo2 Char
c = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
go2 (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
go1
where
go1 :: String -> String
go1 String
"" = String
""
go1 (Char
x:Char
u:Char
l:String
xs) | Char -> Bool
isUpper Char
u Bool -> Bool -> Bool
&& Char -> Bool
isLower Char
l = Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: Char
u Char -> String -> String
forall a. a -> [a] -> [a]
: Char
l Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go1 String
xs
go1 (Char
x:String
xs) = Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go1 String
xs
go2 :: String -> String
go2 String
"" = String
""
go2 (Char
l:Char
u:String
xs) | Char -> Bool
isLower Char
l Bool -> Bool -> Bool
&& Char -> Bool
isUpper Char
u = Char
l Char -> String -> String
forall a. a -> [a] -> [a]
: Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: Char
u Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go2 String
xs
go2 (Char
x:String
xs) = Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go2 String
xs
instance ReflectFlagOptions ImplicitSome where
reflectF :: Proxy ImplicitSome -> RonFlags -> RonFlags
reflectF Proxy ImplicitSome
Proxy RonFlags
f =
RonFlags
f { implicitSome = True }
{-# INLINE reflectF #-}
instance ReflectFlagOptions NoImplicitSome where
reflectF :: Proxy NoImplicitSome -> RonFlags -> RonFlags
reflectF Proxy NoImplicitSome
Proxy RonFlags
f =
RonFlags
f { implicitSome = False }
{-# INLINE reflectF #-}
instance ReflectFlagOptions SkipSingleConstructor where
reflectF :: Proxy SkipSingleConstructor -> RonFlags -> RonFlags
reflectF Proxy SkipSingleConstructor
Proxy RonFlags
f =
RonFlags
f { skipSingleConstructor = True }
{-# INLINE reflectF #-}
instance ReflectFlagOptions NoSkipSingleConstructor where
reflectF :: Proxy NoSkipSingleConstructor -> RonFlags -> RonFlags
reflectF Proxy NoSkipSingleConstructor
Proxy RonFlags
f =
RonFlags
f { skipSingleConstructor = False }
{-# INLINE reflectF #-}