{-# LANGUAGE OverloadedStrings #-} module Data.Eben where import qualified Data.ByteString as B import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as BS import Data.ByteString.Builder (Builder) import qualified Data.ByteString.Builder as BL import Data.Int (Int64) import Data.List (sortOn) import Data.Map.Strict (Map) import qualified Data.Map as M import Data.Monoid ((<>)) data Value = List [Value] | Dict (Map B.ByteString Value) | String B.ByteString | Integer Int64 | Float Float deriving (Eq, Show, Read) decode :: ByteString -> Either String Value decode bs = case BS.uncons bs of ('l', rs) -> () ('d', rs) -> () ('i', rs) -> () ('f', rs) -> () (i , rs) | isDigit i -> encode :: Value -> ByteString encode = BL.toLazyByteString . go where go (List vs) = BL.char7 'l' <> foldMap go vs <> BL.char7 'e' go (Dict vs) = BL.char7 'd' <> mconcat [ str k <> go v | (k, v) <- sortOn fst (M.toList vs) ] <> BL.char7 'e' go (Integer i) = BL.char7 'i' <> BL.string8 (show i) <> BL.char7 'e' go (Float f) = BL.char7 'f' <> BL.floatLE f <> BL.char7 'e' go (String bs) = str bs str bs = BL.intDec (B.length bs) <> BL.char7 ':' <> BL.byteString bs