-----------------------------------------------------------------------------
-- |
-- Module      :  Codec.Utils
-- Copyright   :  (c) Dominic Steinitz 2003
-- License     :  BSD-style (see the file ReadMe.tex)
--
-- Stability   :  experimental
-- Portability :  portable
--
-- Utilities for coding and decoding.
--
-----------------------------------------------------------------------------

module Codec.Utils (
   -- * Types and Constants
   Octet,
   msb,
   -- * Octet Conversion Functions
   fromTwosComp, toTwosComp,
   toOctets, fromOctets,
   listFromOctets, listToOctets,
   i2osp
              ) where

import Data.Word
import Data.Bits

powersOf :: t -> [t]
powersOf t
n = t
1 forall a. a -> [a] -> [a]
: (forall a b. (a -> b) -> [a] -> [b]
map (forall a. Num a => a -> a -> a
*t
n) (t -> [t]
powersOf t
n))

toBase :: b -> b -> [b]
toBase b
x =
   forall a b. (a -> b) -> [a] -> [b]
map forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall a b. (a -> b) -> [a] -> [b]
map (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Integral a => a -> a -> a
mod b
x) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall a. (a -> Bool) -> [a] -> [a]
takeWhile (forall a. Eq a => a -> a -> Bool
/=b
0) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall a. (a -> a) -> a -> [a]
iterate (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Integral a => a -> a -> a
div b
x)

-- | Take a number @x@ convert it to base @n@ as a list of octets.
toOctets :: (Integral a, Integral b) => a -> b -> [Octet]
toOctets :: forall a b. (Integral a, Integral b) => a -> b -> [Octet]
toOctets a
n b
x = (forall {b} {b}. (Integral b, Num b) => b -> b -> [b]
toBase a
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) b
x

-- | This is used to (approximately) get back to a starting word list.
-- For example, if you have a list of 3 Word8 and try to convert them to
-- a Word32, the Word32 will get null-padded, and without correction, you
-- will get 4 Word8s when converting back. This corrects it.
-- Unfortunately, it also means you will have errors if trying to convert
-- Word8 lists with nulls on the end.
trimNulls :: [Word8] -> [Word8]
trimNulls :: [Octet] -> [Octet]
trimNulls = forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
== Octet
0)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse

-- | Converts a list of numbers into a list of octets.
-- The resultant list has nulls trimmed from the end to make this the dual
-- of listFromOctets (except when the original octet list ended with nulls;
-- see 'trimNulls').
listToOctets :: (Bits a, Integral a) => [a] -> [Octet]
listToOctets :: forall a. (Bits a, Integral a) => [a] -> [Octet]
listToOctets [a]
x = [Octet] -> [Octet]
trimNulls forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Octet]]
paddedOctets where
    paddedOctets :: [[Octet]]
    paddedOctets :: [[Octet]]
paddedOctets = forall a b. (a -> b) -> [a] -> [b]
map (Int -> [Octet] -> [Octet]
padTo Int
bytes) [[Octet]]
rawOctets
    rawOctets :: [[Octet]]
    rawOctets :: [[Octet]]
rawOctets = forall a b. (a -> b) -> [a] -> [b]
map (forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Integral b) => a -> b -> [Octet]
toOctets Integer
256) [a]
x
    padTo :: Int -> [Octet] -> [Octet]
    padTo :: Int -> [Octet] -> [Octet]
padTo Int
x [Octet]
y = forall a. Int -> [a] -> [a]
take Int
x forall a b. (a -> b) -> a -> b
$ [Octet]
y forall a. [a] -> [a] -> [a]
++ forall a. a -> [a]
repeat Octet
0
    bytes :: Int
    bytes :: Int
bytes = forall a. Bits a => a -> Int
bitSize (forall a. [a] -> a
head [a]
x) forall a. Integral a => a -> a -> a
`div` Int
8

-- | The basic 8-bit type for encoding and decoding.
type Octet = Word8

-- | The most significant bit of an 'Octet'.
msb :: Int
msb :: Int
msb = forall a. Bits a => a -> Int
bitSize (forall a. HasCallStack => a
undefined::Octet) forall a. Num a => a -> a -> a
- Int
1

-- | Take a list of octets (a number expressed in base n) and convert it
--   to a number.
fromOctets :: (Integral a, Integral b) => a -> [Octet] -> b
fromOctets :: forall a b. (Integral a, Integral b) => a -> [Octet] -> b
fromOctets a
n [Octet]
x =
   forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$
   forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall a b. (a -> b) -> a -> b
$
   forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Num a => a -> a -> a
(*) (forall {t}. Num t => t -> [t]
powersOf a
n) (forall a. [a] -> [a]
reverse (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (Integral a, Num b) => a -> b
fromIntegral [Octet]
x))

-- | See 'listToOctets'.
listFromOctets :: (Integral a, Bits a) => [Octet] -> [a]
listFromOctets :: forall a. (Integral a, Bits a) => [Octet] -> [a]
listFromOctets [] = []
listFromOctets [Octet]
x = [a]
result where
    result :: [a]
result = a
first forall a. a -> [a] -> [a]
: [a]
rest
    first :: a
first = forall a b. (Integral a, Integral b) => a -> [Octet] -> b
fromOctets Integer
256 [Octet]
first'
    first' :: [Octet]
first' = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
take Int
bytes [Octet]
x
    rest :: [a]
rest = forall a. (Integral a, Bits a) => [Octet] -> [a]
listFromOctets forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
drop Int
bytes [Octet]
x
    bytes :: Int
bytes = forall a. Bits a => a -> Int
bitSize a
first forall a. Integral a => a -> a -> a
`div` Int
8

-- | Take the length of the required number of octets and convert the
--   number to base 256 padding it out to the required length. If the
--   required length is less than the number of octets of the converted
--   number then return the converted number. NB this is different from
--   the standard <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf>
--   but mimics how replicate behaves.
i2osp :: Integral a => Int -> a -> [Octet]
i2osp :: forall a. Integral a => Int -> a -> [Octet]
i2osp Int
l a
y =
   [Octet]
pad forall a. [a] -> [a] -> [a]
++ [Octet]
z
      where
         pad :: [Octet]
pad = forall a. Int -> a -> [a]
replicate (Int
l forall a. Num a => a -> a -> a
- Int
unPaddedLen) (Octet
0x00::Octet)
         z :: [Octet]
z = forall a b. (Integral a, Integral b) => a -> b -> [Octet]
toOctets Integer
256 a
y
         unPaddedLen :: Int
unPaddedLen = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Octet]
z

-- | Convert from twos complement.

fromTwosComp :: Integral a => [Octet] -> a
fromTwosComp :: forall a. Integral a => [Octet] -> a
fromTwosComp [Octet]
x =  forall {a}. Num a => [Octet] -> a
conv [Octet]
x
   where conv :: [Octet] -> a
conv []       = a
0
         conv w :: [Octet]
w@(Octet
x:[Octet]
xs) = if (forall a. Bits a => a -> Int -> Bool
testBit Octet
x Int
msb)
                            then forall {a}. Num a => [Octet] -> a
neg [Octet]
w
                            else forall {a}. Num a => [Octet] -> a
pos [Octet]
w
         neg :: [Octet] -> b
neg w :: [Octet]
w@(Octet
x:[Octet]
xs)  = let z :: [Octet]
z=(forall a. Bits a => a -> Int -> a
clearBit Octet
x Int
msb)forall a. a -> [a] -> [a]
:[Octet]
xs in
                            forall a b. (Integral a, Num b) => a -> b
fromIntegral((forall a b. (Integral a, Integral b) => a -> [Octet] -> b
fromOctets Integer
256 [Octet]
z)forall a. Num a => a -> a -> a
-
                                         (Integer
128forall a. Num a => a -> a -> a
*(Integer
256forall a b. (Num a, Integral b) => a -> b -> a
^((forall (t :: * -> *) a. Foldable t => t a -> Int
length [Octet]
w)forall a. Num a => a -> a -> a
-Int
1))))
         pos :: [Octet] -> b
pos [Octet]
w         = forall a b. (Integral a, Num b) => a -> b
fromIntegral(forall a b. (Integral a, Integral b) => a -> [Octet] -> b
fromOctets Integer
256 [Octet]
w)

toTwosComp :: Integral a => a -> [Octet]
toTwosComp :: forall a. Integral a => a -> [Octet]
toTwosComp a
x
   | a
x forall a. Ord a => a -> a -> Bool
< a
0     = forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Octet] -> [Octet]
plusOne forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. (a -> b) -> [a] -> [b]
map forall a. Bits a => a -> a
complement) forall a b. (a -> b) -> a -> b
$ [Octet]
u
   | a
x forall a. Eq a => a -> a -> Bool
== a
0    = [Octet
0x00]
   | Bool
otherwise = [Octet]
u
   where z :: [Octet]
z@(Octet
y:[Octet]
ys) = forall {b} {b}. (Integral b, Num b) => b -> b -> [b]
toBase a
256 (forall a. Num a => a -> a
abs a
x)
         u :: [Octet]
u        = if forall a. Bits a => a -> Int -> Bool
testBit Octet
y Int
msb
                       then Octet
0x00forall a. a -> [a] -> [a]
:[Octet]
z
                       else [Octet]
z

plusOne :: [Octet] -> [Octet]
plusOne :: [Octet] -> [Octet]
plusOne [] = [Octet
1]
plusOne (Octet
x:[Octet]
xs) =
   if Octet
x forall a. Eq a => a -> a -> Bool
== Octet
0xff
      then Octet
0x00forall a. a -> [a] -> [a]
:([Octet] -> [Octet]
plusOne [Octet]
xs)
      else (Octet
xforall a. Num a => a -> a -> a
+Octet
1)forall a. a -> [a] -> [a]
:[Octet]
xs