{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances,UndecidableInstances ,NoMonomorphismRestriction #-}
module Flat.Instances.Mono
( sizeSequence
, encodeSequence
, decodeSequence
, sizeList
, encodeList
, decodeList
, sizeSet
, encodeSet
, decodeSet
, sizeMap
, encodeMap
, decodeMap
, AsArray(..)
, AsList(..)
, AsSet(..)
, AsMap(..)
)
where
import Data.MonoTraversable ( Element
, ofoldl'
, otoList
, MonoFoldable
)
import Data.Sequences ( IsSequence )
import qualified Data.Sequences as S
import Data.Containers
import Flat.Instances.Util
import qualified Data.Foldable as F
newtype AsArray a =
AsArray
{ unArray :: a
} deriving (Show,Eq,Ord)
instance (IsSequence r, Flat (Element r)) => Flat (AsArray r) where
size (AsArray a) = sizeSequence a
encode (AsArray a) = encodeSequence a
decode = AsArray <$> decodeSequence
sizeSequence
:: (IsSequence mono, Flat (Element mono)) => mono -> NumBits -> NumBits
sizeSequence s acc =
let (sz, len) =
ofoldl' (\(acc, l) e -> (size e acc, l + 1)) (acc, 0 :: NumBits) s
in sz + arrayBits len
{-# INLINE sizeSequence #-}
encodeSequence :: (Flat (Element mono), MonoFoldable mono) => mono -> Encoding
encodeSequence = encodeArray . otoList
{-# INLINE encodeSequence #-}
decodeSequence :: (Flat (Element b), IsSequence b) => Get b
decodeSequence = S.fromList <$> decodeArrayWith decode
{-# INLINE decodeSequence #-}
newtype AsList a =
AsList
{ unList :: a
} deriving (Show,Eq,Ord)
instance (IsSequence l, Flat (Element l)) => Flat (AsList l) where
size = sizeList . unList
encode = encodeList . unList
decode = AsList <$> decodeList
{-# INLINE sizeList #-}
sizeList
:: (MonoFoldable mono, Flat (Element mono)) => mono -> NumBits -> NumBits
sizeList l sz = ofoldl' (\s e -> size e (s + 1)) (sz + 1) l
{-# INLINE encodeList #-}
encodeList :: (Flat (Element mono), MonoFoldable mono) => mono -> Encoding
encodeList = encodeListWith encode . otoList
{-# INLINE decodeList #-}
decodeList :: (IsSequence b, Flat (Element b)) => Get b
decodeList = S.fromList <$> decodeListWith decode
newtype AsSet a =
AsSet
{ unSet :: a
} deriving (Show,Eq,Ord)
instance (IsSet set, Flat (Element set)) => Flat (AsSet set) where
size = sizeSet . unSet
encode = encodeSet . unSet
decode = AsSet <$> decodeSet
sizeSet :: (IsSet set, Flat (Element set)) => Size set
sizeSet l acc = ofoldl' (\acc e -> size e (acc + 1)) (acc + 1) $ l
{-# INLINE sizeSet #-}
encodeSet :: (IsSet set, Flat (Element set)) => set -> Encoding
encodeSet = encodeList . setToList
{-# INLINE encodeSet #-}
decodeSet :: (IsSet set, Flat (Element set)) => Get set
decodeSet = setFromList <$> decodeList
{-# INLINE decodeSet #-}
newtype AsMap a =
AsMap
{ unMap :: a
} deriving (Show,Eq,Ord)
instance (IsMap map, Flat (ContainerKey map), Flat (MapValue map)) => Flat (AsMap map) where
size = sizeMap . unMap
encode = encodeMap . unMap
decode = AsMap <$> decodeMap
{-# INLINE sizeMap #-}
sizeMap :: (Flat (ContainerKey r), Flat (MapValue r), IsMap r) => Size r
sizeMap m acc =
F.foldl' (\acc' (k, v) -> size k (size v (acc' + 1))) (acc + 1)
. mapToList
$ m
{-# INLINE encodeMap #-}
encodeMap
:: (Flat (ContainerKey map), Flat (MapValue map), IsMap map)
=> map
-> Encoding
encodeMap = encodeListWith (\(k, v) -> encode k <> encode v) . mapToList
{-# INLINE decodeMap #-}
decodeMap
:: (Flat (ContainerKey map), Flat (MapValue map), IsMap map) => Get map
decodeMap = mapFromList <$> decodeListWith ((,) <$> decode <*> decode)