module Data.Bits.Coded
(
Coded(..)
, Unary(..)
, Elias(..)
, Gamma
, Delta
, runEncode
, runDecode
) where
import Data.Bits
import Data.Bits.Coding
import Data.Bits.Extras
import Data.Bytes.Get
import Data.Bytes.Put
import Data.Foldable
class Coded c where
encode :: MonadPut m => c -> Coding m ()
encodeMany :: (MonadPut m, Foldable t) => t c -> Coding m ()
encodeMany = traverse_ encode
decode :: MonadGet m => Coding m c
newtype Unary n = Unary {
unUnary :: n
} deriving (Eq, Ord, Read, Show, Num, Integral, Real, Enum)
ones :: Integer
ones = oneBits `unsafeShiftL` 1
instance Integral n => Coded (Unary n) where
encode (Unary n) = putBitsFrom (fromIntegral n) ones
decode = do b <- getBit
if b then fmap (1+) decode else return 0
runEncode :: MonadPut m => Coding m () -> m ()
runEncode (Coding c) = c k 0 0
where k _ _ _ = return ()
runDecode :: MonadGet m => Coding m a -> m a
runDecode (Coding c) = c k 0 0
where k a _ _ = return a
newtype Elias c n = Elias {
unElias :: n
} deriving (Eq, Ord, Read, Show, Num, Real, Integral, Enum)
instance (Coded c, Integral c, Ranked n) => Coded (Elias c n) where
encode (Elias n) = do encode (fromIntegral m :: c)
putBitsFrom (pred m) n
where m = msb n
decode = do m :: c <- decode
n <- getBitsFrom (pred $ fromIntegral m) (bit $ fromIntegral m)
return $ Elias n
type Gamma c = Elias (Unary c)
type Delta c n = Elias (Gamma c n) n