{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving ,DeriveGeneric #-}

{-# LANGUAGE CPP #-}
-- |Instances for the containers library
module Flat.Instances.Containers (sizeMap
  , encodeMap
  , decodeMap
) where

import Flat.Instances.Util
import Data.Map 
import Flat.Instances.Base()
import Flat.Instances.Mono
import Data.Tree                                                
import Data.Set
import Data.IntMap 
import Data.Sequence

-- $setup
-- >>> import Flat.Instances.Test
-- >>> import Data.Set
-- >>> import Data.Sequence
-- >>> import Data.IntMap
-- >>> import Data.Map 
-- >>> import Data.Tree      
-- >>> import Flat.Instances.Mono

{-|
Maps are defined as a list of (Key,Value) tuples:

@
Map = List (Key,Value)

List a = Nil | Cons a (List a)
@
-}

{-|
>>> tst (Data.IntMap.empty :: IntMap ())
(True,1,[0])

>>> asList Data.IntMap.fromList [(1,"a"),(2,"b")]
True
-}
instance Flat a => Flat (IntMap a) where
  size :: IntMap a -> NumBits -> NumBits
size = forall r.
(Flat (ContainerKey r), Flat (MapValue r), IsMap r) =>
Size r
sizeMap
  encode :: IntMap a -> Encoding
encode = forall map.
(Flat (ContainerKey map), Flat (MapValue map), IsMap map) =>
map -> Encoding
encodeMap
  decode :: Get (IntMap a)
decode = forall map.
(Flat (ContainerKey map), Flat (MapValue map), IsMap map) =>
Get map
decodeMap

{-|
Maps are encoded as lists:

>>> tst (Data.Map.empty :: Map () ())
(True,1,[0])

>>>  asList Data.Map.fromList [("a","aa"),("b","bb")]
True

Key/Values are encoded in order:

>>> let l = [("a","aa"),("b","bb")] in tst (Data.Map.fromList l) == tst (Data.Map.fromList $ Prelude.reverse l)
True

IntMap and Map are encoded in the same way:

>>> let l = [(2::Int,"b"),(1,"a")] in tst (Data.IntMap.fromList l) == tst (Data.Map.fromList l)
True
-}
instance (Flat a, Flat b, Ord a) => Flat (Map a b) where
  size :: Map a b -> NumBits -> NumBits
size = forall r.
(Flat (ContainerKey r), Flat (MapValue r), IsMap r) =>
Size r
sizeMap
  encode :: Map a b -> Encoding
encode = forall map.
(Flat (ContainerKey map), Flat (MapValue map), IsMap map) =>
map -> Encoding
encodeMap
  decode :: Get (Map a b)
decode = forall map.
(Flat (ContainerKey map), Flat (MapValue map), IsMap map) =>
Get map
decodeMap

{-|
Data.Sequence.Seq is encoded as a list.

>>> asList Data.Sequence.fromList [3::Word8,4,7]
True

In flat <0.4, it was encoded as an Array.

If you want to restore the previous behaviour, use AsArray:

>>> tst $ AsArray (Data.Sequence.fromList [11::Word8,22,33])
(True,40,[3,11,22,33,0])

>>> tst $ Data.Sequence.fromList [11::Word8,22,33]
(True,28,[133,197,164,32])
-}
instance Flat a => Flat (Seq a) where
 size :: Seq a -> NumBits -> NumBits
size = forall mono.
(MonoFoldable mono, Flat (Element mono)) =>
mono -> NumBits -> NumBits
sizeList -- . toList
 encode :: Seq a -> Encoding
encode = forall mono.
(Flat (Element mono), MonoFoldable mono) =>
mono -> Encoding
encodeList -- . Data.Sequence.toList
 decode :: Get (Seq a)
decode = forall a. [a] -> Seq a
Data.Sequence.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall b. (IsSequence b, Flat (Element b)) => Get b
decodeList

{-|
Data.Set is encoded as a list

>>> asList Data.Set.fromList [3::Word8,4,7]
True
-}
instance (Flat a,Ord a) => Flat (Set a) where
  size :: Set a -> NumBits -> NumBits
size = forall set. (IsSet set, Flat (Element set)) => Size set
sizeSet
  encode :: Set a -> Encoding
encode = forall set. (IsSet set, Flat (Element set)) => set -> Encoding
encodeSet
  decode :: Get (Set a)
decode = forall set. (IsSet set, Flat (Element set)) => Get set
decodeSet

{-|
>>>  tst (Node (1::Word8) [Node 2 [Node 3 []], Node 4 []])
(True,39,[1,129,64,200,32])
-}
#if ! MIN_VERSION_containers(0,5,8)
deriving instance Generic (Tree a)
#endif

instance (Flat a) => Flat (Tree a)