|
@@ -24,19 +24,56 @@ data Value
|
|
|
deriving (Eq, Show, Read)
|
|
|
|
|
|
decode :: ByteString -> Maybe (Value, ByteString)
|
|
|
-decode bs = go
|
|
|
- where go = case BS.uncons bs of
|
|
|
- Just (108, rs) -> decodeList
|
|
|
- Just (100, rs) -> decodeDict
|
|
|
- Just (105, rs) -> decodeInt
|
|
|
- Just (102, rs) -> decodeFloat
|
|
|
+decode = go
|
|
|
+ where go bs = case BS.uncons bs of
|
|
|
+ Just (108, rs) -> decodeList [] rs
|
|
|
+ Just (100, rs) -> decodeDict [] rs
|
|
|
+ Just (105, rs) -> decodeInt rs
|
|
|
+ Just (102, rs) -> decodeFloat rs
|
|
|
Just (i , rs)
|
|
|
- | isDigit (fromIntegral i) ->
|
|
|
- let (is, rs') = BS.break (== 58) rs
|
|
|
- len = toNum (toDigit i) is
|
|
|
- (str, rs'') = BS.splitAt len (BS.tail rs')
|
|
|
- in Just (String (BS.toStrict str), rs'')
|
|
|
+ | isDigit (fromIntegral i) -> do
|
|
|
+ (s, rs) <- decodeBS bs
|
|
|
+ return (String s, rs)
|
|
|
| otherwise -> Nothing
|
|
|
+ decodeList ls bs = case BS.uncons bs of
|
|
|
+ Just (101, rs) -> Just (List ls, rs)
|
|
|
+ _ -> do
|
|
|
+ (x, rs) <- go bs
|
|
|
+ decodeList (ls ++ [x]) rs
|
|
|
+ decodeDict ls bs = case BS.uncons bs of
|
|
|
+ Just (101, rs) -> Just (Dict (M.fromList ls), rs)
|
|
|
+ _ -> do
|
|
|
+ (k, rs) <- decodeBS bs
|
|
|
+ (v, rs') <- go rs
|
|
|
+ decodeDict ((k,v):ls) rs'
|
|
|
+ decodeInt bs =
|
|
|
+ let (is, rs) = BS.break (== 101) bs
|
|
|
+ in return (Integer (toNum 0 is), BS.tail rs)
|
|
|
+ decodeFloat bs =
|
|
|
+ let (fs, rs) = BS.splitAt 4 bs
|
|
|
+ in return (Float 0.0, BS.tail rs)
|
|
|
+ decodeBS bs =
|
|
|
+ let (is, rs') = BS.break (== 58) bs
|
|
|
+ len = toNum 0 is
|
|
|
+ (str, rs'') = BS.splitAt len (BS.tail rs')
|
|
|
+ in Just (BS.toStrict str, rs'')
|
|
|
+
|
|
|
+asDict :: Value -> Maybe (Map B.ByteString Value)
|
|
|
+asDict (Dict ds) = Just ds
|
|
|
+asDict _ = Nothing
|
|
|
+
|
|
|
+asList :: Value -> Maybe [Value]
|
|
|
+asList (List ls) = Just ls
|
|
|
+asList _ = Nothing
|
|
|
+
|
|
|
+asFloat :: Value -> Maybe Float
|
|
|
+asFloat (Float f) = Just f
|
|
|
+asFloat (Integer i) = Just (fromIntegral i)
|
|
|
+asFloat _ = Nothing
|
|
|
+
|
|
|
+lookup :: B.ByteString -> Value -> Maybe Value
|
|
|
+lookup k (Dict ds) = M.lookup k ds
|
|
|
+lookup _ _ = Nothing
|
|
|
|
|
|
isDigit :: Word8 -> Bool
|
|
|
isDigit n = n >= 48 && n <= 57
|
|
@@ -46,10 +83,9 @@ toDigit n = fromIntegral n - 48
|
|
|
|
|
|
toNum :: Int64 -> ByteString -> Int64
|
|
|
toNum n (BS.uncons->Just(b, bs)) =
|
|
|
- toNum (n * 10 + fromIntegral b) bs
|
|
|
+ toNum (n * 10 + toDigit b) bs
|
|
|
toNum n _ = n
|
|
|
|
|
|
-
|
|
|
encode :: Value -> ByteString
|
|
|
encode = BL.toLazyByteString . go
|
|
|
where go (List vs) =
|