module Data.ASN1.Internal
( uintOfBytes
, intOfBytes
, bytesOfUInt
, bytesOfInt
, putVarEncodingIntegral
) where
import Data.Word
import Data.Bits
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
uintOfBytes :: ByteString -> (Int, Integer)
uintOfBytes :: ByteString -> (Int, Integer)
uintOfBytes b :: ByteString
b = (ByteString -> Int
B.length ByteString
b, (Integer -> Word8 -> Integer) -> Integer -> ByteString -> Integer
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
B.foldl (\acc :: Integer
acc n :: Word8
n -> (Integer
acc Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL` 8) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Word8 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
n) 0 ByteString
b)
bytesOfUInt :: Integer -> [Word8]
bytesOfUInt :: Integer -> [Word8]
bytesOfUInt x :: Integer
x = [Word8] -> [Word8]
forall a. [a] -> [a]
reverse (Integer -> [Word8]
forall t a. (Integral t, Num a, Bits a, Bits t) => t -> [a]
list Integer
x)
where list :: t -> [a]
list i :: t
i = if t
i t -> t -> Bool
forall a. Ord a => a -> a -> Bool
<= 0xff then [t -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
i] else (t -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
i a -> a -> a
forall a. Bits a => a -> a -> a
.&. 0xff) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: t -> [a]
list (t
i t -> Int -> t
forall a. Bits a => a -> Int -> a
`shiftR` 8)
intOfBytes :: ByteString -> (Int, Integer)
intOfBytes :: ByteString -> (Int, Integer)
intOfBytes b :: ByteString
b
| ByteString -> Int
B.length ByteString
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = (0, 0)
| Bool
otherwise = (Int
len, if Bool
isNeg then -(Integer
maxIntLen Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
v Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1) else Integer
v)
where
(len :: Int
len, v :: Integer
v) = ByteString -> (Int, Integer)
uintOfBytes ByteString
b
maxIntLen :: Integer
maxIntLen = 2 Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
len) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1
isNeg :: Bool
isNeg = Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit (ByteString -> Word8
B.head ByteString
b) 7
bytesOfInt :: Integer -> [Word8]
bytesOfInt :: Integer -> [Word8]
bytesOfInt i :: Integer
i
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> 0 = if Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit ([Word8] -> Word8
forall a. [a] -> a
head [Word8]
uints) 7 then 0 Word8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
: [Word8]
uints else [Word8]
uints
| Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = [0]
| Bool
otherwise = if Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit ([Word8] -> Word8
forall a. [a] -> a
head [Word8]
nints) 7 then [Word8]
nints else 0xff Word8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
: [Word8]
nints
where
uints :: [Word8]
uints = Integer -> [Word8]
bytesOfUInt (Integer -> Integer
forall a. Num a => a -> a
abs Integer
i)
nints :: [Word8]
nints = [Word8] -> [Word8]
forall a. [a] -> [a]
reverse ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall a b. (a -> b) -> a -> b
$ [Word8] -> [Word8]
forall a. (Num a, Eq a) => [a] -> [a]
plusOne ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall a b. (a -> b) -> a -> b
$ [Word8] -> [Word8]
forall a. [a] -> [a]
reverse ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall a b. (a -> b) -> a -> b
$ (Word8 -> Word8) -> [Word8] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map Word8 -> Word8
forall a. Bits a => a -> a
complement ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall a b. (a -> b) -> a -> b
$ [Word8]
uints
plusOne :: [a] -> [a]
plusOne [] = [1]
plusOne (x :: a
x:xs :: [a]
xs) = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== 0xff then 0 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a]
plusOne [a]
xs else (a
xa -> a -> a
forall a. Num a => a -> a -> a
+1) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs
putVarEncodingIntegral :: (Bits i, Integral i) => i -> ByteString
putVarEncodingIntegral :: i -> ByteString
putVarEncodingIntegral i :: i
i = ByteString -> ByteString
B.reverse (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ((i, Bool) -> Maybe (Word8, (i, Bool))) -> (i, Bool) -> ByteString
forall a. (a -> Maybe (Word8, a)) -> a -> ByteString
B.unfoldr (i, Bool) -> Maybe (Word8, (i, Bool))
forall a a.
(Integral a, Bits a, Bits a, Num a) =>
(a, Bool) -> Maybe (a, (a, Bool))
genOctets (i
i,Bool
True)
where genOctets :: (a, Bool) -> Maybe (a, (a, Bool))
genOctets (x :: a
x,first :: Bool
first)
| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> 0 =
let out :: a
out = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
x a -> a -> a
forall a. Bits a => a -> a -> a
.&. 0x7F) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (if Bool
first then 0 else 0x80) in
(a, (a, Bool)) -> Maybe (a, (a, Bool))
forall a. a -> Maybe a
Just (a
out, (a -> Int -> a
forall a. Bits a => a -> Int -> a
shiftR a
x 7, Bool
False))
| Bool
otherwise = Maybe (a, (a, Bool))
forall a. Maybe a
Nothing