packages feed

RLP 1.0.1 → 1.1.0

raw patch · 6 files changed

+293/−104 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Serialize.RLP: instance Data.Serialize.RLP.RLPSerialize a => Data.Serialize.RLP.RLPSerialize (GHC.Maybe.Maybe a)
- Data.Serialize.RLP: fromBigEndian :: ByteString -> Int
+ Data.Serialize.RLP: fromBigEndian :: ByteString -> Either String Int
- Data.Serialize.RLP: fromBigEndianS :: ByteString -> Int
+ Data.Serialize.RLP: fromBigEndianS :: ByteString -> Either String Int
- Data.Serialize.RLP: fromRLP :: RLPSerialize a => RLPT -> a
+ Data.Serialize.RLP: fromRLP :: RLPSerialize a => RLPT -> Maybe a
- Data.Serialize.RLP: rlpDecode :: RLPSerialize a => ByteString -> Maybe a
+ Data.Serialize.RLP: rlpDecode :: RLPSerialize a => ByteString -> Either String a

Files

ChangeLog.md view
@@ -1,5 +1,13 @@ # Revision history for RLP +## 1.1.0 -- 2018-12-10++* Added error handling support. Check the generated haddock documentation where examples have been placed.++## 1.0.1 -- 2018-12-04++* Just added support for strings on the default types that are already instances of `RLPSerialize`+ ## 1.0.0  -- 2018-12-01  * First version.
README.md view
@@ -9,4 +9,12 @@  For more information, please check the haddock documentation (can be generated running `cabal haddock` on the root of the repo). -Feel free to contribute.+## Installation++On 1.1.0 error handling was coded as a safe way to fail on the decoding through Eithers. Usage of >=1.1 is quite advised.++Installation can be easily done through `cabal` as the package is in Hackage. `cabal install RLP` should be enough.++## Contribuition++Feel free to contribute. I think the error handling part could be improved.
RLP.cabal view
@@ -1,5 +1,5 @@ Name:                   RLP-Version:                1.0.1+Version:                1.1.0 Author:                 Javier Sagredo <jasataco@gmail.com> Maintainer:             Javier Sagredo <jasataco@gmail.com> License:                LGPL-3
src/Data/Serialize/RLP.hs view
@@ -37,6 +37,9 @@   -- * Example   -- $example   +  -- * Errors and special cases+  -- $failexample+   ) where  import Data.Serialize.RLP.Internal@@ -64,10 +67,14 @@ -- understanding of the generated code. -- -- It is important to remark that although it can't be imposed, it doesn't make sense to try--- to transform to RLP types with more than one constructor. The transformation should encode+-- to transform to RLP types with more than one constructor that don't difer in structure.+-- The transformation should encode  -- a way to find out which of the constructors belongs to the data so not only data is being -- encoded in the result, also information about the structure futher than the actual length -- prefixes. That's why it only makes sense to transform to RLP types with just one constructor.+-- On the other hand, it's perfectly viable to encode types with more than one constructor if+-- the structure of each of them is different as it can be adjusted via pattern matching+-- strategies.  -------------------------------------------------------------------------------- @@ -75,7 +82,7 @@ -- For encoding and decoding values with the RLP protocol, 'toRLP' and 'fromRLP' have to -- be implemented. ----- Instances of RLPSerialize have to satisfy the following property:+-- Instances of RLPSerialize are expected to satisfy the following property: -- -- > fromRLP . toRLP == id --@@ -88,8 +95,9 @@ class RLPSerialize a where   -- | Transform a value to the 'RLPT' structure that best fits its internal structure   toRLP :: a -> RLPT-  -- | Transform an 'RLPT' structure back into the value it represents-  fromRLP :: RLPT -> a+  -- | Transform an 'RLPT' structure back into the value it represents.+  -- Its return type is 'Maybe a' because it can fail+  fromRLP :: RLPT -> Maybe a    -- | Transform a value to an 'RLPT' structure and then encode it following the   -- RLP standard.@@ -97,9 +105,15 @@   rlpEncode = rlpEncodeI . toRLP    -- | Transform a ByteString to an 'RLPT' structure following the RLP standard and-  -- then transform it to the original type.-  rlpDecode :: DBSL.ByteString -> Maybe a-  rlpDecode x = maybe Nothing fromRLP $ rlpDecodeI x+  -- then transform it to the original type. It returns 'Left s' when failing on the+  -- decoding of the transforming from RLPT into the required type, and 'Right v' on+  -- success.+  rlpDecode :: DBSL.ByteString -> Either String a+  rlpDecode x = case rlpDecodeI x :: Either String RLPT of+                  Left m  -> Left m+                  Right v -> case fromRLP v of+                    Nothing -> Left "RLPT value couldn't ve transformed into the required type"+                    Just v' -> Right v'    {-# MINIMAL toRLP, fromRLP #-} @@ -107,15 +121,15 @@ instance RLPSerialize RLPT where   toRLP = id -  fromRLP = id+  fromRLP = Just . id  -- ByteStrings just have to be encapsulated -- Also, it only makes sense to disencapsulate from a ByteString instance RLPSerialize DBS.ByteString where   toRLP = RLPB -  fromRLP (RLPB b) = b-  fromRLP _ = undefined+  fromRLP (RLPB b) = Just b+  fromRLP _ = Nothing  -- Ints have to be transformed into its Big-endian form -- and then they are treated as ByteStrings.@@ -125,15 +139,22 @@ instance RLPSerialize Int where   toRLP = toRLP . toBigEndianS -  fromRLP = fromBigEndianS . (fromRLP :: RLPT -> DBS.ByteString)+  fromRLP =  maybe Nothing (\s -> case fromBigEndianS s of+                               Left _  -> Nothing+                               Right v -> Just v ) . (fromRLP :: RLPT -> Maybe DBS.ByteString)  -- Serializing lists implies making a list with the serialization -- of each element instance {-# OVERLAPPABLE #-} RLPSerialize a => RLPSerialize [a] where   toRLP = RLPL . map toRLP -  fromRLP (RLPL x) = map fromRLP x-  fromRLP _        = undefined+  fromRLP (RLPL x) = if any (\a -> case a of+                                Nothing -> True+                                _ -> False) r+                     then Nothing+                     else Just $ map unJust r+    where r = map fromRLP x+  fromRLP _        = Nothing  -- Bools are serialized as [0] or [1] in a ByteArray -- THIS IS AN ASUMPTION considering Bool equivalent to@@ -143,59 +164,99 @@   toRLP False = RLPB $ toByteStringS "\NUL"    fromRLP x-    | x == toRLP True = True-    | otherwise       = False+    | x == toRLP True  = Just True+    | x == toRLP False = Just False+    | otherwise        = Nothing  -- Strings are serialized as ByteStrings instance {-# OVERLAPPING #-} RLPSerialize String where   toRLP = RLPB . toByteStringS   -  fromRLP (RLPB x) = fromByteStringS x-  fromRLP _        = undefined+  fromRLP (RLPB x) = Just $ fromByteStringS x+  fromRLP _        = Nothing  -- Chars are just length-one strings instance RLPSerialize Char where   toRLP = RLPB . toByteStringS . (: []) -  fromRLP (RLPB x) = head $ fromByteStringS x-  fromRLP _        = undefined+  fromRLP (RLPB x) = Just $ head $ fromByteStringS x+  fromRLP _        = Nothing  -- Tuples are transformed into Lists instance (RLPSerialize a, RLPSerialize b) => RLPSerialize (a, b) where   toRLP (x, y) = RLPL [toRLP x, toRLP y] -  fromRLP (RLPL [x, y]) = (fromRLP x, fromRLP y)-  fromRLP _             = undefined+  fromRLP (RLPL [x, y]) =+    maybe Nothing+     (\x' -> maybe Nothing+       (\y' -> Just (x', y'))+       (fromRLP y))+     (fromRLP x)+  fromRLP _             = Nothing  instance (RLPSerialize a, RLPSerialize b, RLPSerialize c) => RLPSerialize (a, b, c) where   toRLP (x, y, z) = RLPL [toRLP x, toRLP y, toRLP z] -  fromRLP (RLPL [x, y, z]) = (fromRLP x, fromRLP y, fromRLP z)-  fromRLP _                = undefined-+  fromRLP (RLPL [x, y, z]) =+    maybe Nothing+     (\x' -> maybe Nothing+       (\y' -> maybe Nothing+         (\z' -> Just (x', y', z'))+         (fromRLP z))+       (fromRLP y))+     (fromRLP x)+  fromRLP _             = Nothing+  instance (RLPSerialize a, RLPSerialize b, RLPSerialize c, RLPSerialize d) => RLPSerialize (a, b, c, d) where   toRLP (a1, a2, a3, a4) = RLPL [toRLP a1, toRLP a2, toRLP a3, toRLP a4] -  fromRLP (RLPL [a1, a2, a3, a4]) = (fromRLP a1, fromRLP a2, fromRLP a3, fromRLP a4)-  fromRLP _                       = undefined+  fromRLP (RLPL [a1, a2, a3, a4]) =+    maybe Nothing+     (\a1' -> maybe Nothing+      (\a2' -> maybe Nothing+       (\a3' -> maybe Nothing+        (\a4' -> Just (a1', a2', a3', a4'))+        (fromRLP a4))+       (fromRLP a3))+      (fromRLP a2))+     (fromRLP a1)+  fromRLP _             = Nothing  instance (RLPSerialize a, RLPSerialize b, RLPSerialize c, RLPSerialize d, RLPSerialize e) => RLPSerialize (a, b, c, d, e) where   toRLP (a1, a2, a3, a4, a5) = RLPL [toRLP a1, toRLP a2, toRLP a3, toRLP a4, toRLP a5] -  fromRLP (RLPL [a1, a2, a3, a4, a5]) = (fromRLP a1, fromRLP a2, fromRLP a3, fromRLP a4, fromRLP a5)-  fromRLP _                           = undefined+  fromRLP (RLPL [a1, a2, a3, a4, a5]) =+    maybe Nothing+     (\a1' -> maybe Nothing+      (\a2' -> maybe Nothing+       (\a3' -> maybe Nothing+        (\a4' -> maybe Nothing+         (\a5' -> Just (a1', a2', a3', a4', a5'))+         (fromRLP a5))+        (fromRLP a4))+       (fromRLP a3))+      (fromRLP a2))+     (fromRLP a1)+  fromRLP _             = Nothing  instance (RLPSerialize a, RLPSerialize b, RLPSerialize c, RLPSerialize d, RLPSerialize e, RLPSerialize f) => RLPSerialize (a, b, c, d, e, f) where   toRLP (a1, a2, a3, a4, a5, a6) = RLPL [toRLP a1, toRLP a2, toRLP a3, toRLP a4, toRLP a5, toRLP a6] -  fromRLP (RLPL [a1, a2, a3, a4, a5, a6]) = (fromRLP a1, fromRLP a2, fromRLP a3, fromRLP a4, fromRLP a5, fromRLP a6)-  fromRLP _                               = undefined---- Needed by the default rlpDecode implementation-instance RLPSerialize a => RLPSerialize (Maybe a) where-  toRLP = undefined--  fromRLP = Just . fromRLP+  fromRLP (RLPL [a1, a2, a3, a4, a5, a6]) =+    maybe Nothing+     (\a1' -> maybe Nothing+      (\a2' -> maybe Nothing+       (\a3' -> maybe Nothing+        (\a4' -> maybe Nothing+         (\a5' -> maybe Nothing+          (\a6' -> Just (a1', a2', a3', a4', a5', a6'))+          (fromRLP a6))+         (fromRLP a5))+        (fromRLP a4))+       (fromRLP a3))+      (fromRLP a2))+     (fromRLP a1)+  fromRLP _             = Nothing  -------------------------------------------------------------------------------- @@ -213,24 +274,61 @@ -- -- Then we have to make it an instance of RLPSerialize: --  --- > instance RLPSerialize Person where--- >   toRLP p = RLPL [--- >                 RLPL [--- >                     toRLP . toByteStringS . fst . name $ p,--- >                     toRLP . toByteStringS . snd . name $ p--- >                     ],--- >                 toRLP . age $ p]--- > --- >   fromRLP (RLPL [ RLPL [ RLPB a, RLPB b ], RLPB c ]) =--- >          Person (fromByteStringS a, fromByteStringS b) (fromBigEndianS c :: Int)+-- >instance RLPSerialize Person where+-- >  toRLP p = RLPL [+-- >                RLPL [+-- >                    toRLP . toByteStringS . fst . name $ p,+-- >                    toRLP . toByteStringS . snd . name $ p+-- >                    ],+-- >                toRLP . age $ p]+-- >+-- >  fromRLP (RLPL [ RLPL [ RLPB a, RLPB b ], RLPB c ]) =+-- >    case fromBigEndianS c of+-- >      Right v -> Just $ Person (fromByteStringS a, fromByteStringS b) v+-- >      _       -> Nothing+-- >  fromRLP _ = Nothing -- --- This way, if the decoding gives rise to other structure than the expected, a runtime--- exception will be thrown by the pattern matching. We can now use our decoder and encoder+-- This way, if the decoding gives rise to other structure than the expected, a the+-- resulting value would be 'Nothing'. We can now use our decoder and encoder -- with our custom type: -- -- > p = Person ("John", "Snow") 33 -- > e = rlpEncode p -- > -- "\204\202\132John\132Snow!" ~ [204,202,132,74,111,104,110,132,83,110,111,119,33] -- > rlpDecode e :: Maybe Person--- > -- Just (Person {name = ("John","Snow"), age = 33})+-- > -- Right (Person {name = ("John","Snow"), age = 33}) --++--------------------------------------------------------------------------------++-- $failexample+-- In case we run into an error situation, depending whether the RLPT structure is not well+-- formed or the generated structure couldn't be transformed into the expected type, an error+-- is returned in the form of a 'Left' value.+--+-- Just to see this as an example, if we chop the resulting ByteString, there's no way to+-- generate a correct RLPT structure so an error is thrown:+--+-- > rlpDecode $ DBSL.take 6 $ rlpEncode $ RLPL [ RLPB $ toByteStringS "John", RLPB $ toByteStringS "Snow" ] :: Either String RLPT+-- > -- Left "not enough bytes"+--+-- On the other hand, if we try to transform an incorrect value from the decoded RLPT we+-- generate a new error:+--+-- > rlpDecode $ rlpEncode $ RLPB $ toByteStringS "\STX" :: Either String Bool+-- > -- Left "RLPT value couldn't ve transformed into the required type"+--+-- If a ByteString is the result of the concatenation of more than one serialized RLPT structure,+-- only the first one would be decoded:+--+-- > rlpDecode $ rlpEncode $ RLPB $ toByteStringS "\STX" :: Either String Bool+-- > -- Left "RLPT value couldn't ve transformed into the required type"+--+-- If a ByteString is the result of the concatenation of more than one serialized RLPT structure,+-- only the first one would be decoded:+--+-- > a = rlpEncode $ RLPL [ RLPB $ toByteStringS "John", RLPB $ toByteStringS "Snow" ]+-- > b = DBSL.append a a+-- > -- "\202\132John\132Snow\202\132John\132Snow"+-- > rlpDecode b :: Either String RLPT+-- > -- Right (RLPL [RLPB "John",RLPB "Snow"])
src/Data/Serialize/RLP/Internal.hs view
@@ -12,6 +12,8 @@   toByteStringS,   fromByteString,   fromByteStringS,++  unJust,          RLPT(..)       ) where@@ -23,7 +25,9 @@ import qualified Data.ByteString.Char8        as DBSC import qualified Data.ByteString.Lazy         as DBSL import qualified Data.ByteString.Lazy.Char8   as DBSLC+import qualified Data.List                    as DL + --------------------------------------------------------------------------------  -- | The 'RLPT' type represents the result of transforming the@@ -48,15 +52,18 @@ toBigEndianS :: Int -> DBS.ByteString toBigEndianS = DBSL.toStrict . toBigEndian -fromBigEndian :: DBSL.ByteString -> Int-fromBigEndian bs =  fromIntegral . runGet getInt64be $ bs'+fromBigEndian :: DBSL.ByteString -> Either String Int+fromBigEndian bs =  case bs'' of+                      Left (_, _, msg) -> Left ("can't decode from Big-Endian: " ++ msg)+                      Right (_, _, a)  -> Right $ fromIntegral a   where bs' = case () of           _ | DBSL.length bs >= 8 -> bs             | otherwise -> DBSLC.append (DBSLC.pack $ b) bs                      where b = take (8 - (fromIntegral . DBSL.length $ bs)) (repeat '\NUL')+        bs'' = runGetOrFail getInt64be $ bs'                             -- | Strict version of 'fromBigEndian'-fromBigEndianS :: DBS.ByteString -> Int+fromBigEndianS :: DBS.ByteString -> Either String Int fromBigEndianS = fromBigEndian . DBSL.fromStrict  toByteString :: String -> DBSL.ByteString@@ -74,32 +81,64 @@ fromByteStringS = DBSC.unpack  -- | Internal function for spliting the array in chunks of bytes-rlpSplit :: DBSL.ByteString -> [DBSL.ByteString]+rlpSplit :: DBSL.ByteString -> Either String [DBSL.ByteString] rlpSplit x-  | DBSL.null x        = []+  | DBSL.null x        = Right []   | DBSL.head x <  192 =       case () of-        _ | DBSL.head x < 128 -> (DBSL.singleton . DBSL.head $ x) : (rlpSplit $ DBSL.tail x)+        _ | DBSL.head x < 128 ->+              let aux = rlpSplit $ DBSL.tail x in+                  case aux of+                    Left m  -> Left m+                    Right v -> Right $ (DBSL.singleton . DBSL.head $ x) : v           | DBSL.head x < 183 ->               let size = (fromIntegral $ DBSL.head x) - 128 :: Int in                 let total = size + 1 in-                  (DBSL.take (fromIntegral total) x) : (rlpSplit $ DBSL.drop (fromIntegral total) x)+                  let aux = rlpSplit $ DBSL.drop (fromIntegral total) x in+                    case aux of+                      Left m  -> Left m+                      Right v -> Right $ (DBSL.take (fromIntegral total) x) : v           | otherwise        ->-                    let sizeSize = (fromIntegral $ DBSL.head x) - 183 :: Int in-                      let size = fromBigEndian . DBSL.take (fromIntegral sizeSize) . DBSL.tail $ x :: Int in-                        let total = sizeSize + size + 1 :: Int in -                          (DBSL.take (fromIntegral total) x) : (rlpSplit $ DBSL.drop (fromIntegral total) x)-  | DBSL.head x == 192 = (DBSL.singleton $ DBSL.head x) : (rlpSplit $ DBSL.tail x)+              let sizeSize = (fromIntegral $ DBSL.head x) - 183 :: Int in+                let size = fromBigEndian . DBSL.take (fromIntegral sizeSize) . DBSL.tail $ x in+                  case size of+                    Left m  -> Left m+                    Right v ->+                      let total = sizeSize + v + 1 :: Int in+                        let aux = rlpSplit $ DBSL.drop (fromIntegral total) x in+                            case aux of+                              Left m  -> Left m+                              Right v' -> Right $ (DBSL.take (fromIntegral total) x) : v'+  | DBSL.head x == 192 =+    let aux = (rlpSplit $ DBSL.tail x) in+      case aux of+        Left m  -> Left m+        Right v -> Right $ (DBSL.singleton $ DBSL.head x) : v   | DBSL.head x <  247 =       let size = (fromIntegral $ DBSL.head x) - 192 :: Int in         let total = size + 1 in-          (DBSL.take (fromIntegral total) x) : (rlpSplit $ DBSL.drop (fromIntegral total) x)+          let aux = rlpSplit $ DBSL.drop (fromIntegral total) x in+            case aux of+              Left m  -> Left m+              Right v -> Right $ (DBSL.take (fromIntegral total) x) : v+             | otherwise          =       let sizeSize = (fromIntegral $ DBSL.head x) - 247 :: Int in-        let size = fromBigEndian . DBSL.take (fromIntegral sizeSize) . DBSL.tail $ x :: Int in-          let total = sizeSize + size + 1 :: Int in -            (DBSL.take (fromIntegral total) x) : (rlpSplit $ DBSL.drop (fromIntegral total) x)+        let size = fromBigEndian . DBSL.take (fromIntegral sizeSize) . DBSL.tail $ x in+          case size of+            Left m  -> Left m+            Right v -> +              let total = sizeSize + v + 1 :: Int in+                let aux = rlpSplit $ DBSL.drop (fromIntegral total) x in+                  case aux of+                    Left m  -> Left m+                    Right v' -> Right $ (DBSL.take (fromIntegral total) x) : v' +-- Just for internal porpouses+unJust :: Maybe a -> a+unJust (Just x) = x+unJust _        = undefined+ --------------------------------------------------------------------------------  -- | The 'RLPEncodeable' class groups the RLPT, ByteString and Int types@@ -120,11 +159,11 @@   rlpDecodeI' :: Get a    -- Mainly run rlpDecodeI'-  rlpDecodeI :: DBSL.ByteString -> Maybe a+  rlpDecodeI :: DBSL.ByteString -> Either String a   rlpDecodeI x = let r = runGetOrFail rlpDecodeI' x in                    case r of-                     Left _          -> Nothing-                     Right (_, _, s) -> Just s+                     Left (_, _, m)  -> Left m+                     Right (_, _, s) -> Right s  -------------------------------------------------------------------------------- -- Instances@@ -145,17 +184,43 @@     case () of        _ | i < 192 -> do         -- ByteArray             ls <- getRemainingLazyByteString-            return . RLPB . (\(Just x) -> x) . rlpDecodeI $ DBSL.cons i ls+            let r = rlpDecodeI $ DBSL.cons i ls+            case r of+              Left m  -> fail m+              Right v -> return . RLPB $ v         | i == 192 -> do        -- Empty list             return $ RLPL []         | i < 247 -> do         -- Small list             ls <- getLazyByteString . fromIntegral $ i - 192-            return $ RLPL . map ((\(Just x) -> x) . rlpDecodeI) . rlpSplit $ ls+            let k = rlpSplit ls+            case k of+              Left m  -> fail m+              Right v -> do+                let k' = map rlpDecodeI v+                let k'' = map (\e -> case e of+                                  Left m  -> m+                                  Right _ -> "") k'+                case all null k'' of+                  True -> return $ RLPL . map (\(Right x) -> x) $ k'+                  _    -> fail (DL.intercalate ", " k'')         | otherwise -> do       -- Big List             ls <- getLazyByteString . fromIntegral $ i - 247             let k = fromBigEndian ls-            ls' <- getLazyByteString . fromIntegral $ k-            return $ RLPL . map ((\(Just x) -> x) . rlpDecodeI) . rlpSplit $ ls'+            case k of+              Left m  -> fail m+              Right v -> do+                ls' <- getLazyByteString . fromIntegral $ v+                let k' = rlpSplit ls'+                case k' of+                  Left m'  -> fail m'+                  Right v' -> do+                    let k'' = map rlpDecodeI v'+                    let k'3 = map (\e -> case e of+                                  Left m  -> m+                                  Right _ -> "") k''+                    case all null k'3 of+                      True -> return $ RLPL . map (\(Right x) -> x) $ k''+                      _    -> fail (DL.intercalate ", " k'3)  instance RLPEncodeable DBS.ByteString where   rlpEncodeI' bs@@ -176,13 +241,20 @@             return ls         | i < 192 -> do             sbe <- getLazyByteString . fromIntegral $ i - 183-            ls <- getByteString . fromBigEndian $ sbe-            return ls-        | otherwise -> undefined+            let k = fromBigEndian sbe+            case k of+              Left m  -> fail m+              Right v -> do+                ls <- getByteString v+                return ls+        | otherwise -> fail "Decoding a ByteString with head >= 192"  instance RLPEncodeable Int where-  rlpEncodeI' = rlpEncodeI' . DBSL.toStrict . toBigEndian+  rlpEncodeI' = rlpEncodeI' . toBigEndianS    rlpDecodeI' = do     b <- rlpDecodeI' :: Get DBS.ByteString-    return . fromBigEndian . DBSL.fromStrict $ b+    let k = fromBigEndianS b+    case k of+      Left m  -> fail m+      Right v -> return v
test/Data/Serialize/RLPSpec.hs view
@@ -10,6 +10,9 @@ main :: IO () main = hspec spec +type ESB = Either String DBS.ByteString+type ESR = Either String RLPT+ spec :: Spec spec = do   context "when encoding _empty_ values" $ do@@ -17,86 +20,86 @@       (DBSL.unpack . rlpEncode . toByteStringS $ "") `shouldBe` [ 0x80 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS $ "" :: Maybe DBS.ByteString) `shouldBe` (Just $ toByteStringS "")+      (rlpDecode . rlpEncode . toByteStringS $ "" :: ESB) `shouldBe` Right (toByteStringS "")      it "should encode the empty list" $ do       (DBSL.unpack . rlpEncode . RLPL $ []) `shouldBe` [ 0xc0 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . RLPL $ [] :: Maybe RLPT) `shouldBe` (Just $ RLPL []) +      (rlpDecode . rlpEncode . RLPL $ [] :: ESR) `shouldBe` Right (RLPL [])       it "should encode the integer Zero" $ do       (DBSL.unpack . rlpEncode . toRLP $ (0 :: Int)) `shouldBe` [ 0x80 ]      it "should decode it back" $ do-      (maybe Nothing fromRLP $ rlpDecode . rlpEncode . toRLP $ (0 :: Int) :: Maybe Int) `shouldBe` (Just 0)+      ((\(Right b) -> fromBigEndianS b) $ (rlpDecode . rlpEncode . toRLP $ (0 :: Int) :: ESB)) `shouldBe` (Right 0)    context "when encoding ByteArrays" $ do     it "should encode an array of length 1 and small value" $ do       (DBSL.unpack . rlpEncode . toByteStringS $ "\NUL") `shouldBe` [ 0x00 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS $ "\NUL" :: Maybe DBS.ByteString) `shouldBe` (Just $ toByteStringS "\NUL")+      (rlpDecode . rlpEncode . toByteStringS $ "\NUL" :: ESB) `shouldBe` Right (toByteStringS "\NUL")      it "should encode an array of length 1 and big value" $ do       (DBSL.unpack . rlpEncode . toByteStringS $ "\150") `shouldBe` [ 0x81, 0x96 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS $ "\150" :: Maybe DBS.ByteString) `shouldBe` (Just $ toByteStringS "\150")+      (rlpDecode . rlpEncode . toByteStringS $ "\150" :: ESB) `shouldBe` Right (toByteStringS "\150")      it "should encode an array of length bigger than one and smaller than 56" $ do       (DBSL.unpack . rlpEncode . toByteStringS $ "\SOH\SOH") `shouldBe` [ 0x82, 0x01, 0x01 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS $ "\SOH\SOH" :: Maybe DBS.ByteString) `shouldBe` (Just $ toByteStringS "\SOH\SOH")+      (rlpDecode . rlpEncode . toByteStringS $ "\SOH\SOH" :: ESB) `shouldBe` Right (toByteStringS "\SOH\SOH")      it "should encode an array of length bigger than 56 with _small_ length" $ do       (DBSL.unpack . rlpEncode . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1)         `shouldBe` ([ 0xb8, 0x3c ] ++ (Prelude.take 60 . Prelude.repeat $ 0x01))      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 :: Maybe DBS.ByteString)-        `shouldBe` (Just $ toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 0x01)+      (rlpDecode . rlpEncode . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 :: ESB)+        `shouldBe` Right (toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 0x01)      it "should encode an array of length bigger than 56 with _big_ length" $ do       (DBSL.unpack . rlpEncode . toByteStringS . Prelude.map toEnum . Prelude.take 43520 . Prelude.repeat $ 1)         `shouldBe` ([ 0xb9, 0xaa, 0x00 ] ++ (Prelude.take 43520 . Prelude.repeat $ 0x01))      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS . Prelude.map toEnum . Prelude.take 43520 . Prelude.repeat $ 1 :: Maybe DBS.ByteString)-        `shouldBe` (Just $ toByteStringS . Prelude.map toEnum . Prelude.take 43520 . Prelude.repeat $ 0x01)+      (rlpDecode . rlpEncode . toByteStringS . Prelude.map toEnum . Prelude.take 43520 . Prelude.repeat $ 1 :: ESB)+        `shouldBe` Right (toByteStringS . Prelude.map toEnum . Prelude.take 43520 . Prelude.repeat $ 0x01)    context "when encoding RLP structures" $ do     it "should encode RLP structures with less than 56 bytes and one element" $ do       (DBSL.unpack . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" ]) `shouldBe` [ 0xc1, 0x00 ]          it "should decode it back" $ do-      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" ] :: Maybe RLPT)-        `shouldBe` (Just $ RLPL [ RLPB . toByteStringS $ "\NUL" ])+      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" ] :: ESR)+        `shouldBe` Right (RLPL [ RLPB . toByteStringS $ "\NUL" ])      it "should encode RLP structures with less than 56 bytes and more than one element" $ do       (DBSL.unpack . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS $ "\NUL" ] ])         `shouldBe` [ 0xc3, 0x00, 0xc1, 0x00 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS $ "\NUL" ] ] :: Maybe RLPT)-        `shouldBe` (Just $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS $ "\NUL" ] ])+      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS $ "\NUL" ] ] :: ESR)+        `shouldBe` Right (RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS $ "\NUL" ] ])      it "should encode RLP structures with more than 56 bytes and one element" $ do       (DBSL.unpack . rlpEncode $ RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ])         `shouldBe` ([ 0xf8, 0x3e, 0xb8, 0x3c ] ++ (Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 0x01))      it "should decode it back" $ do-      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] :: Maybe RLPT)-        `shouldBe` (Just $ RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ])+      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] :: ESR)+        `shouldBe` Right (RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ])      it "should encode RLP structures with more than 56 bytes and more than one element" $ do       (DBSL.unpack . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] ])         `shouldBe` ([ 0xf8, 0x41, 0x00,  0xf8, 0x3e, 0xb8, 0x3c ] ++ (Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 0x01))      it "should decode it back" $ do-      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] ] :: Maybe RLPT)-        `shouldBe` (Just $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] ])+      (rlpDecode . rlpEncode $ RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] ] :: ESR)+        `shouldBe` Right (RLPL [ RLPB . toByteStringS $ "\NUL" , RLPL [ RLPB . toByteStringS . Prelude.map toEnum . Prelude.take 60 . Prelude.repeat $ 1 ] ])     context "when running Ethereum examples" $ do@@ -104,28 +107,28 @@       (DBSL.unpack . rlpEncode . toByteStringS $ "dog") `shouldBe` [ 0x83, 0x64, 0x6f, 0x67 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS $ "dog" :: Maybe DBS.ByteString) `shouldBe` (Just $ toByteStringS "dog")+      (rlpDecode . rlpEncode . toByteStringS $ "dog" :: ESB) `shouldBe` Right (toByteStringS "dog")      it "should encode [ cat, dog ]" $ do       (DBSL.unpack . rlpEncode . RLPL . Prelude.map (RLPB . toByteStringS) $ [ "cat", "dog" ])         `shouldBe` [ 0xc8, 0x83, 0x63, 0x61, 0x74, 0x83, 0x64, 0x6f, 0x67 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . RLPL . Prelude.map (RLPB . toByteStringS) $ [ "cat", "dog" ] :: Maybe RLPT)-        `shouldBe` (Just $ RLPL . Prelude.map (RLPB . toByteStringS) $ [ "cat", "dog" ])+      (rlpDecode . rlpEncode . RLPL . Prelude.map (RLPB . toByteStringS) $ [ "cat", "dog" ] :: ESR)+        `shouldBe` Right (RLPL . Prelude.map (RLPB . toByteStringS) $ [ "cat", "dog" ])      it "should encode the set theoretical representation" $ do       (DBSL.unpack . rlpEncode . toRLP $ RLPL [ RLPL [] , RLPL [ RLPL [] ] , RLPL [ RLPL [] , RLPL [ RLPL [] ] ] ])         `shouldBe` [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toRLP $ RLPL [ RLPL [] , RLPL [ RLPL [] ] , RLPL [ RLPL [] , RLPL [ RLPL [] ] ] ] :: Maybe RLPT)-        `shouldBe` (Just $ RLPL [ RLPL [] , RLPL [ RLPL [] ] , RLPL [ RLPL [] , RLPL [ RLPL [] ] ] ])+      (rlpDecode . rlpEncode . toRLP $ RLPL [ RLPL [] , RLPL [ RLPL [] ] , RLPL [ RLPL [] , RLPL [ RLPL [] ] ] ] :: ESR)+        `shouldBe` Right (RLPL [ RLPL [] , RLPL [ RLPL [] ] , RLPL [ RLPL [] , RLPL [ RLPL [] ] ] ])      it "should encode LOREM IPSUM" $ do         (DBSL.unpack . rlpEncode . toByteStringS $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit")           `shouldBe` [ 0xb8, 0x38, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x69, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x69, 0x74 ]      it "should decode it back" $ do-      (rlpDecode . rlpEncode . toByteStringS $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit" :: Maybe DBS.ByteString)-        `shouldBe` (Just $ toByteStringS $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit")+      (rlpDecode . rlpEncode . toByteStringS $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit" :: ESB)+        `shouldBe` Right (toByteStringS $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit")