{-# LANGUAGE BangPatterns #-}
module Crypto.Number.Serialize.Internal.LE
( i2osp
, i2ospOf
, os2ip
) where
import Crypto.Number.Compat
import Crypto.Number.Basic
import Data.Bits
import Data.Memory.PtrMethods
import Data.Word (Word8)
import Foreign.Ptr
import Foreign.Storable
i2osp :: Integer -> Ptr Word8 -> Int -> IO Int
i2osp :: Integer -> Ptr Word8 -> Int -> IO Int
i2osp Integer
m Ptr Word8
ptr Int
ptrSz
| Int
ptrSz forall a. Ord a => a -> a -> Bool
<= Int
0 = forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
| Integer
m forall a. Ord a => a -> a -> Bool
< Integer
0 = forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
| Integer
m forall a. Eq a => a -> a -> Bool
== Integer
0 = forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Word8
ptr Int
0 (Word8
0 :: Word8) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return Int
1
| Int
ptrSz forall a. Ord a => a -> a -> Bool
< Int
sz = forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
| Bool
otherwise = Ptr Word8 -> Int -> Integer -> IO ()
fillPtr Ptr Word8
ptr Int
sz Integer
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return Int
sz
where
!sz :: Int
sz = Integer -> Int
numBytes Integer
m
i2ospOf :: Integer -> Ptr Word8 -> Int -> IO Int
i2ospOf :: Integer -> Ptr Word8 -> Int -> IO Int
i2ospOf Integer
m Ptr Word8
ptr Int
ptrSz
| Int
ptrSz forall a. Ord a => a -> a -> Bool
<= Int
0 = forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
| Integer
m forall a. Ord a => a -> a -> Bool
< Integer
0 = forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
| Int
ptrSz forall a. Ord a => a -> a -> Bool
< Int
sz = forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
| Bool
otherwise = do
Ptr Word8 -> Word8 -> Int -> IO ()
memSet Ptr Word8
ptr Word8
0 Int
ptrSz
Ptr Word8 -> Int -> Integer -> IO ()
fillPtr Ptr Word8
ptr Int
sz Integer
m
forall (m :: * -> *) a. Monad m => a -> m a
return Int
ptrSz
where
!sz :: Int
sz = Integer -> Int
numBytes Integer
m
fillPtr :: Ptr Word8 -> Int -> Integer -> IO ()
fillPtr :: Ptr Word8 -> Int -> Integer -> IO ()
fillPtr Ptr Word8
p Int
sz Integer
m = Integer -> Ptr Word8 -> GmpSupported (IO ())
gmpExportIntegerLE Integer
m Ptr Word8
p forall a. GmpSupported a -> a -> a
`onGmpUnsupported` forall {t}. Integral t => Int -> t -> IO ()
export Int
0 Integer
m
where
export :: Int -> t -> IO ()
export Int
ofs t
i
| Int
ofs forall a. Ord a => a -> a -> Bool
>= Int
sz = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = do
let (t
i', t
b) = t
i forall a. Integral a => a -> a -> (a, a)
`divMod` t
256
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Word8
p Int
ofs (forall a b. (Integral a, Num b) => a -> b
fromIntegral t
b :: Word8)
Int -> t -> IO ()
export (Int
ofsforall a. Num a => a -> a -> a
+Int
1) t
i'
os2ip :: Ptr Word8 -> Int -> IO Integer
os2ip :: Ptr Word8 -> Int -> IO Integer
os2ip Ptr Word8
ptr Int
ptrSz
| Int
ptrSz forall a. Ord a => a -> a -> Bool
<= Int
0 = forall (m :: * -> *) a. Monad m => a -> m a
return Integer
0
| Bool
otherwise = Int -> Ptr Word8 -> GmpSupported (IO Integer)
gmpImportIntegerLE Int
ptrSz Ptr Word8
ptr forall a. GmpSupported a -> a -> a
`onGmpUnsupported` Integer -> Int -> Ptr Word8 -> IO Integer
loop Integer
0 (Int
ptrSzforall a. Num a => a -> a -> a
-Int
1) Ptr Word8
ptr
where
loop :: Integer -> Int -> Ptr Word8 -> IO Integer
loop :: Integer -> Int -> Ptr Word8 -> IO Integer
loop !Integer
acc Int
i !Ptr Word8
p
| Int
i forall a. Ord a => a -> a -> Bool
< Int
0 = forall (m :: * -> *) a. Monad m => a -> m a
return Integer
acc
| Bool
otherwise = do
Word8
w <- forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Word8
p Int
i :: IO Word8
Integer -> Int -> Ptr Word8 -> IO Integer
loop ((Integer
acc forall a. Bits a => a -> Int -> a
`shiftL` Int
8) forall a. Bits a => a -> a -> a
.|. forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w) (Int
iforall a. Num a => a -> a -> a
-Int
1) Ptr Word8
p