packages feed

text-encode-0.2.0.0: src/text-encode-persistent/Text/Encode/Persistent.hs

{- | Derive 'PersistField' using 'TextEncode'.

@
    data MyType = ...

    instance 'TextEncode' MyType where ...

    deriving via 'ViaTextEncode' MyType instance 'PersistField' MyType
@
-}
module Text.Encode.Persistent (
    module Text.Encode,
    PersistentEncode (..),
) where

import Text.Encode

import Data.Bifunctor (first)
import Data.Coerce (coerce)
import Data.Typeable (Typeable)
import Database.Persist.Class (PersistField (..))
import Database.Persist.PersistValue (PersistValue (..))
import Text.Convert (asString, asText)

instance (TextEncode a, Typeable a) => PersistField (ViaTextEncode a) where
    {-# INLINE toPersistValue #-}
    toPersistValue = coerce $ PersistText . encodeText @(ViaTextEncode a)

    fromPersistValue (PersistText bs) = coerce $ first asText $ decodeText @(ViaTextEncode a) bs
    fromPersistValue x = Left $ asText $ "DeriveTextEncode PersistentEncode requires PersistText: " <> show x

{- | Derive 'TextEncode' using 'PersistField'.

@
    data MyType = ...

    instance 'FromPersistField' MyType where ...

    deriving via 'PersistentEncoding' MyType instance 'TextEncode' MyType
@

__N.B.__ Do not use this on any type for which you are using 'ViaTextEncode' to
derive 'PersistField'. Your code will loop infinitely.
-}
newtype PersistentEncode a = PersistentEncode a
    deriving (PersistField) via a

instance (PersistField a) => TextPrimitives (PersistentEncode a) where
    textEncode x =
        case toPersistValue x of
            (PersistText txt) -> txt
            x' -> error $ "PersistentEncode requires PersistText: " <> show x'

    textDecode = first asString . fromPersistValue . PersistText
    {-# INLINE textDecode #-}

deriving via TextEncoding (PersistentEncode a) instance (PersistField a) => TextEncode (PersistentEncode a)