{-# 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 :: input
-> output
-> UArray (Unit input)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
convertFromTo input
inputEncodingTy output
outputEncodingTy UArray (Unit input)
bytes
| UArray (Unit input) -> Bool
forall ty. UArray ty -> Bool
Vec.null UArray (Unit input)
bytes = Either (Offset (Unit input), Error input) (UArray (Unit output))
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (Offset (Unit input), Error input) (UArray (Unit output))
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output))))
-> (UArray (Unit output)
-> Either
(Offset (Unit input), Error input) (UArray (Unit output)))
-> UArray (Unit output)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. UArray (Unit output)
-> Either (Offset (Unit input), Error input) (UArray (Unit output))
forall (m :: * -> *) a. Monad m => a -> m a
return (UArray (Unit output)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output))))
-> UArray (Unit output)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
forall a b. (a -> b) -> a -> b
$ UArray (Unit output)
forall a. Monoid a => a
mempty
| Bool
otherwise = UArray (Unit input)
-> ((Offset (Unit input) -> Unit input)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output))))
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
forall (prim :: * -> *) ty a.
(PrimMonad prim, PrimType ty) =>
UArray ty -> ((Offset ty -> ty) -> prim a) -> prim a
Vec.unsafeIndexer UArray (Unit input)
bytes (((Offset (Unit input) -> Unit input)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output))))
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output))))
-> ((Offset (Unit input) -> Unit input)
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output))))
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
forall a b. (a -> b) -> a -> b
$ \Offset (Unit input) -> Unit input
t -> Int
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
-> st
(Either (Offset (Unit input), Error input) (UArray (Unit output)))
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 Offset (Unit input)
forall a. Additive a => a
azero Offset (Unit input) -> Unit input
t)
where
lastUnit :: CountOf (Unit input)
lastUnit = UArray (Unit input) -> CountOf (Unit input)
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 Offset (Unit input) -> CountOf (Unit input) -> Bool
forall ty. Offset ty -> CountOf ty -> Bool
.==# CountOf (Unit input)
lastUnit = ()
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = case input
-> (Offset (Unit input) -> Unit input)
-> Offset (Unit input)
-> Either (Error input) (Char, Offset (Unit input))
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 -> Failure
(Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input))
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
forall (m :: * -> *). MonadFailure m => Failure m -> m ()
mFail (Offset (Unit input)
off, Error input
err)
Right (Char
c, Offset (Unit input)
noff) -> output
-> Char
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
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 Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
-> Builder
(UArray (Unit output))
(MUArray (Unit output))
(Unit output)
st
(Offset (Unit input), Error input)
()
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