module Codec.Goat.ValueFrame.Decode
( valueDecode
) where
import Data.Bits
import Data.Bits.Floating
import Data.List
import Data.List.Split
import Data.Word
import qualified Data.ByteString as B
import Codec.Goat.ValueFrame.Types
import Codec.Goat.Util
type Context = ([Bool], (Int, Int))
valueDecode :: ValueFrame
-> [Float]
valueDecode (ValueFrame Nothing _ _ ) = []
valueDecode (ValueFrame (Just x) len bs)
| B.null bs || len == 0 = [coerceToFloat x]
| otherwise = map coerceToFloat (x:xors)
where
xors = drop 1 $ scanl xor x ws :: [Word32]
ws = unfoldr decode (bits, (16, 16)) :: [Word32]
bits = genericTake len (unpackBits bs) :: [Bool]
decode :: Context
-> Maybe (Word32, Context)
decode (False:xs, bounds) = Just (0, (xs, bounds))
decode (True:False:xs, bounds) = Just $ inside bounds xs
decode (True:True:xs, _ ) = Just $ outside xs
decode (_, _ ) = Nothing
inside :: (Int, Int)
-> [Bool]
-> (Word32, Context)
inside bounds@(lead, trail) xs = (fromBools number, (ys, bounds))
where
number = surround (lead, trail) bits
(bits, ys) = splitAt (32 lead trail) xs
outside :: [Bool]
-> (Word32, Context)
outside xs = (fromBools number, (ys, (lead, trail)))
where
[lead, size] = map fromBools $ splitPlaces ([5, 6] :: [Int]) xs
trail = 32 lead size
number = surround (lead, trail) bits
(bits, ys) = splitAt size (drop 11 xs)
surround :: (Int, Int)
-> [Bool]
-> [Bool]
surround (lead, trail) = (replicate lead False ++) . (++ replicate trail False)