{- TODO 2023-02-15 raehik
Encoding shouldn't change to a bytestring, for efficiency. Due to convenient
representations, we can efficiently serialize a Text directly to a builder,
skipping intermediate ByteString conversion.

Hm. Maybe that means it should be changed to the builder. What does that mean
for decoding?
-}

module Binrep.Type.Text
  ( AsText
  , Encode(..), encode, encodeToRep
  , Decode(..)

  , module Binrep.Type.Text.Encoding.Utf8
  , module Binrep.Type.Text.Encoding.Ascii
  , module Binrep.Type.Text.Encoding.Utf16
  , module Binrep.Type.Text.Encoding.Utf32
  , module Binrep.Type.Text.Encoding.ShiftJis

  ) where

import Binrep.Type.Text.Internal

import Refined

import Binrep.Type.Text.Encoding.Utf8
import Binrep.Type.Text.Encoding.Ascii
import Binrep.Type.Text.Encoding.Utf16
import Binrep.Type.Text.Encoding.Utf32
import Binrep.Type.Text.Encoding.ShiftJis

-- | Encode some validated text.
encode :: forall enc. Encode enc => AsText enc -> Bytes
encode :: forall {k} (enc :: k). Encode enc => AsText enc -> Bytes
encode = forall (enc :: k). Encode enc => Text -> Bytes
forall {k} (enc :: k). Encode enc => Text -> Bytes
encode' @enc (Text -> Bytes) -> (AsText enc -> Text) -> AsText enc -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AsText enc -> Text
forall {k} (p :: k) x. Refined p x -> x
unrefine

-- | Encode some text to a bytestring, asserting that the resulting value is
--   valid for the requested bytestring representation.
--
-- This is intended to be used with visible type applications:
--
-- >>> let Right t = refine @UTF8 (Text.pack "hi")
-- >>> :t t
-- t :: AsText UTF8
-- >>> let Right bs = encodeToRep @'C t
-- >>> :t bs
-- bs :: Refined 'C Bytes
encodeToRep
    :: forall rep enc
    .  (Encode enc, Predicate rep Bytes)
    => AsText enc
    -> Either RefineException (Refined rep Bytes)
encodeToRep :: forall {k} {k} (rep :: k) (enc :: k).
(Encode enc, Predicate rep Bytes) =>
AsText enc -> Either RefineException (Refined rep Bytes)
encodeToRep = Bytes -> Either RefineException (Refined rep Bytes)
forall {k} (p :: k) x.
Predicate p x =>
x -> Either RefineException (Refined p x)
refine (Bytes -> Either RefineException (Refined rep Bytes))
-> (AsText enc -> Bytes)
-> AsText enc
-> Either RefineException (Refined rep Bytes)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AsText enc -> Bytes
forall {k} (enc :: k). Encode enc => AsText enc -> Bytes
encode