module Vaultaire.Types.ContentsResponse
(
ContentsResponse(..),
) where
import Control.Applicative ((<$>), (<*>))
import Control.Exception (SomeException (..))
import qualified Data.ByteString as S
import Data.Packer (getBytes, getWord64LE, putBytes, putWord64LE, putWord8,
runPacking, runUnpacking)
import Test.QuickCheck
import Vaultaire.Classes.WireFormat
import Vaultaire.Types.Address
import Vaultaire.Types.SourceDict
data ContentsResponse = RandomAddress Address
| InvalidContentsOrigin
| ContentsListEntry Address SourceDict
| EndOfContentsList
| UpdateSuccess
| RemoveSuccess
deriving (Show, Eq)
instance WireFormat ContentsResponse where
fromWire bs
| bs == "\x00" = Right InvalidContentsOrigin
| bs == "\x03" = Right EndOfContentsList
| bs == "\x04" = Right UpdateSuccess
| bs == "\x05" = Right RemoveSuccess
| S.take 1 bs == "\x01" = RandomAddress <$> fromWire (S.drop 1 bs)
| S.take 1 bs == "\x02" = do
let body = S.drop 1 bs
let unpacker = (,) <$> getBytes 8 <*> (getWord64LE >>= getBytes . fromIntegral)
let (addr_bytes, dict_bytes ) = runUnpacking unpacker body
ContentsListEntry <$> fromWire addr_bytes <*> fromWire dict_bytes
| otherwise = Left $ SomeException $
userError "Invalid ContentsResponse packet"
toWire InvalidContentsOrigin = "\x00"
toWire (RandomAddress addr) = "\x01" `S.append` toWire addr
toWire (ContentsListEntry addr dict) =
let addr_bytes = toWire addr
dict_bytes = toWire dict
dict_len = S.length dict_bytes
in runPacking (dict_len + 17) $ do
putWord8 0x2
putBytes addr_bytes
putWord64LE $ fromIntegral dict_len
putBytes dict_bytes
toWire EndOfContentsList = "\x03"
toWire UpdateSuccess = "\x04"
toWire RemoveSuccess = "\x05"
instance Arbitrary ContentsResponse where
arbitrary = oneof [ RandomAddress <$> arbitrary
, ContentsListEntry <$> arbitrary <*> arbitrary
, return EndOfContentsList
, return UpdateSuccess
, return RemoveSuccess ]