{-# LANGUAGE FlexibleContexts #-}
module Basement.String.Encoding.Encoding
( Encoding(..)
, convertFromTo
) where
import Basement.Compat.Base
import Basement.Types.OffsetSize
import Basement.Monad
import Basement.PrimType
import Basement.MutableBuilder
import Basement.Numerical.Additive
import Basement.UArray (UArray)
import Basement.UArray.Mutable (MUArray)
import qualified Basement.UArray as Vec
class Encoding encoding where
type Unit encoding
type Error encoding
encodingNext :: encoding
-> (Offset (Unit encoding) -> Unit encoding)
-> Offset (Unit encoding)
-> Either (Error encoding) (Char, Offset (Unit encoding))
encodingWrite :: (PrimMonad st, Monad st)
=> encoding
-> Char
-> Builder (UArray (Unit encoding))
(MUArray (Unit encoding))
(Unit encoding) st err ()
convertFromTo :: ( PrimMonad st, Monad st
, Encoding input, PrimType (Unit input)
, Encoding output, PrimType (Unit output)
)
=> input
-> output
-> UArray (Unit input)
-> st (Either (Offset (Unit input), Error input) (UArray (Unit output)))
convertFromTo :: forall (st :: * -> *) input output.
(PrimMonad st, Monad st, Encoding input, PrimType (Unit input),
Encoding output, PrimType (Unit output)) =>
input
-> output
-> UArray (Unit input)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
convertFromTo input
inputEncodingTy output
outputEncodingTy UArray (Unit input)
bytes
| forall ty. UArray ty -> Bool
Vec.null UArray (Unit input)
bytes = forall (m :: * -> *) a. Monad m => a -> m a
return forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => a
mempty
| Bool
otherwise = forall (prim :: * -> *) ty a.
(PrimMonad prim, PrimType ty) =>
UArray ty -> ((Offset ty -> ty) -> prim a) -> prim a
Vec.unsafeIndexer UArray (Unit input)
bytes forall a b. (a -> b) -> a -> b
$ \Offset (Unit input) -> Unit input
t -> forall ty (m :: * -> *) err.
(PrimType ty, PrimMonad m) =>
Int
-> Builder (UArray ty) (MUArray ty) ty m err ()
-> m (Either err (UArray ty))
Vec.builderBuild Int
64 (Offset (Unit input)
-> (Offset (Unit input) -> Unit input)
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
loop forall a. Additive a => a
azero Offset (Unit input) -> Unit input
t)
where
lastUnit :: CountOf (Unit input)
lastUnit = forall ty. UArray ty -> CountOf ty
Vec.length UArray (Unit input)
bytes
loop :: Offset (Unit input)
-> (Offset (Unit input) -> Unit input)
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
loop Offset (Unit input)
off Offset (Unit input) -> Unit input
getter
| Offset (Unit input)
off forall ty. Offset ty -> CountOf ty -> Bool
.==# CountOf (Unit input)
lastUnit = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = case forall encoding.
Encoding encoding =>
encoding
-> (Offset (Unit encoding) -> Unit encoding)
-> Offset (Unit encoding)
-> Either (Error encoding) (Char, Offset (Unit encoding))
encodingNext input
inputEncodingTy Offset (Unit input) -> Unit input
getter Offset (Unit input)
off of
Left Error input
err -> forall (m :: * -> *). MonadFailure m => Failure m -> m ()
mFail (Offset (Unit input)
off, Error input
err)
Right (Char
c, Offset (Unit input)
noff) -> forall encoding (st :: * -> *) err.
(Encoding encoding, PrimMonad st, Monad st) =>
encoding
-> Char
-> Builder
(UArray (Unit encoding))
(MUArray (Unit encoding))
(Unit encoding)
st
err
()
encodingWrite output
outputEncodingTy Char
c forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Offset (Unit input)
-> (Offset (Unit input) -> Unit input)
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
loop Offset (Unit input)
noff Offset (Unit input) -> Unit input
getter