never executed always true always false
    1 {-# LANGUAGE FlexibleContexts #-}
    2 
    3 -- |
    4 -- Copyright: © 2018-2020 IOHK
    5 -- License: Apache-2.0
    6 
    7 module Data.Word7
    8     (
    9       -- * Types
   10       Word7
   11 
   12       -- * Conversions
   13     , toWord7
   14     , toWord8
   15     , toWord7s
   16     , toNatural
   17 
   18       -- * Encode / Decode
   19     , putVariableLengthNat
   20     , getVariableLengthNat
   21     ) where
   22 
   23 import Prelude
   24 
   25 import Data.Binary.Get
   26     ( Get, getWord8 )
   27 import Data.Binary.Put
   28     ( Put, putWord8 )
   29 import Data.Bits
   30     ( shiftL, shiftR, (.&.), (.|.) )
   31 import Data.List
   32     ( foldl' )
   33 import Data.Word
   34     ( Word8 )
   35 import Numeric.Natural
   36     ( Natural )
   37 
   38 
   39 -- | A 'Word7' algebraic data-type.
   40 -- @since 2.0.0
   41 newtype Word7 = Word7 Word8
   42   deriving (Eq, Show)
   43 
   44 
   45 --
   46 -- Conversions
   47 --
   48 -- > toWord7 1
   49 -- > Word7 1
   50 -- > toWord7 127
   51 -- > Word7 127
   52 -- > toWord7 128
   53 -- > Word7 0
   54 toWord7 :: Word8 -> Word7
   55 toWord7 x = Word7 (x .&. 0x7F)
   56 
   57 toWord8 :: Word7 -> Word8
   58 toWord8 (Word7 x) = x
   59 
   60 -- > toWord7s 1
   61 -- > [Word7 1]
   62 -- > toWord7s 128
   63 -- > [Word7 1,Word7 0]
   64 -- > toWord7s 19099
   65 -- > [Word7 1,Word7 21,Word7 27]
   66 toWord7s :: Natural -> [Word7]
   67 toWord7s = reverse . go
   68   where
   69     go n
   70         | n <= 0x7F = [Word7 . fromIntegral $ n]
   71         | otherwise = (toWord7 . fromIntegral) n : go (shiftR n 7)
   72 
   73 word7sToNat :: [Word7] -> Natural
   74 word7sToNat = foldl' f 0
   75   where
   76     f n (Word7 r) = shiftL n 7 .|. (fromIntegral r)
   77 
   78 toNatural :: [Word7] -> Natural
   79 toNatural =
   80     fst .
   81     foldr (\(Word7 x) (res, pow) ->
   82                (res + (fromIntegral x)*(limit pow + 1), pow + 7)
   83           )
   84     (0,0)
   85   where
   86     limit :: Int -> Natural
   87     limit pow = 2 ^ pow - 1
   88 
   89 --
   90 -- Decoding
   91 --
   92 putVariableLengthNat :: Natural -> Put
   93 putVariableLengthNat = putWord7s . toWord7s
   94   where
   95     putWord7s :: [Word7] -> Put
   96     putWord7s [] = pure ()
   97     putWord7s [Word7 x] = putWord8 x
   98     putWord7s (Word7 x : xs) = putWord8 (x .|. 0x80) >> putWord7s xs
   99 
  100 getVariableLengthNat :: Get Natural
  101 getVariableLengthNat = word7sToNat <$> getWord7s
  102   where
  103     getWord7s :: Get [Word7]
  104     getWord7s = do
  105       next <- getWord8
  106       case next .&. 0x80 of
  107         0x80 -> (:) (toWord7 next) <$> getWord7s
  108         _ -> pure [Word7 next]