packages feed

flat-0.6: src/Flat/AsSize.hs

{-# LANGUAGE InstanceSigs              #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE ScopedTypeVariables       #-}

{- |
Wrapper type to decode a value to its size in bits.

See also "Flat.AsBin".

In 0.5.X this type was called @SizeOf@.

@since 0.6
-}
module Flat.AsSize(AsSize(..)) where

import           Flat.Class         (Flat (..))
import           Flat.Decoder.Prim  (sizeOf)
import           Flat.Decoder.Types (Get)
import           Flat.Types         (NumBits)

-- $setup
-- >>> :set -XScopedTypeVariables
-- >>> import Flat.Instances.Base
-- >>> import Flat.Instances.Text
-- >>> import Flat.Decoder.Types
-- >>> import Flat.Types
-- >>> import Flat.Run
-- >>> import Data.Word
-- >>> import qualified Data.Text as T

{- |
Useful to skip unnecessary values and to check encoding sizes.

Examples:

Ignore the second and fourth component of a tuple:

>>> let v = flat ('a',"abc",'z',True) in unflat v :: Decoded (Char,AsSize String,Char,AsSize Bool)
Right ('a',AsSize 28,'z',AsSize 1)

Notice the variable size encoding of Words:

>>> unflat (flat (1::Word16,1::Word64)) :: Decoded (AsSize Word16,AsSize Word64)
Right (AsSize 8,AsSize 8)

Text:

>>> unflat (flat (T.pack "",T.pack "a",T.pack "主",UTF8Text $ T.pack "主",UTF16Text $ T.pack "主",UTF16Text $ T.pack "a")) :: Decoded (AsSize T.Text,AsSize T.Text,AsSize T.Text,AsSize UTF8Text,AsSize UTF16Text,AsSize UTF16Text)
Right (AsSize 16,AsSize 32,AsSize 48,AsSize 48,AsSize 40,AsSize 40)

Various encodings:

>>> unflat (flat (False,[T.pack "",T.pack "a",T.pack "主"],'a')) :: Decoded (AsSize Bool,AsSize [T.Text],AsSize Char)
Right (AsSize 1,AsSize 96,AsSize 8)
-}
newtype AsSize a = AsSize NumBits deriving (Eq,Ord,Show)

instance Flat a => Flat (AsSize a) where
    size :: Flat a => AsSize a -> NumBits -> NumBits
    size = error "unused"

    encode = error "unused"

    decode :: Flat a => Get (AsSize a)
    decode = AsSize <$> sizeOf (decode :: Get a)