{-# LANGUAGE OverloadedStrings #-}
module Botan.Low.ZFEC (
ZFECShare
, zfecEncode
, zfecDecode
) where
import Botan.Bindings.ConstPtr (ConstPtr (..))
import Botan.Bindings.ZFEC
import Botan.Low.Error.Internal
import Botan.Low.Internal.ByteString
import Botan.Low.Make
import Control.DeepSeq
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import Data.Word
import Foreign.C.Types
import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import Foreign.Ptr
type ZFECShare = (Int, ByteString)
zfecEncode
:: Int
-> Int
-> ByteString
-> IO [ZFECShare]
zfecEncode :: Int -> Int -> ByteString -> IO [ZFECShare]
zfecEncode Int
k Int
n ByteString
input = ByteString
-> (Ptr Word8 -> CSize -> IO [ZFECShare]) -> IO [ZFECShare]
forall byte a. ByteString -> (Ptr byte -> CSize -> IO a) -> IO a
asBytesLen ByteString
input ((Ptr Word8 -> CSize -> IO [ZFECShare]) -> IO [ZFECShare])
-> (Ptr Word8 -> CSize -> IO [ZFECShare]) -> IO [ZFECShare]
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
inputPtr CSize
inputLen -> do
let shareSize :: Int
shareSize = Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
inputLen) Int
k
Int -> (Ptr Word8 -> IO [ZFECShare]) -> IO [ZFECShare]
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
shareSize) ((Ptr Word8 -> IO [ZFECShare]) -> IO [ZFECShare])
-> (Ptr Word8 -> IO [ZFECShare]) -> IO [ZFECShare]
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
outPtr -> do
Int -> (Ptr (Ptr Word8) -> IO [ZFECShare]) -> IO [ZFECShare]
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
n ((Ptr (Ptr Word8) -> IO [ZFECShare]) -> IO [ZFECShare])
-> (Ptr (Ptr Word8) -> IO [ZFECShare]) -> IO [ZFECShare]
forall a b. (a -> b) -> a -> b
$ \ (Ptr (Ptr Word8)
sharePtrArrayPtr :: Ptr (Ptr Word8)) -> do
let sharePtrs :: [Ptr Word8]
sharePtrs = (Int -> Ptr Word8) -> [Int] -> [Ptr Word8]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Ptr Word8 -> Int -> Ptr Word8
forall a. Storable a => Ptr a -> Int -> Ptr a
advancePtr Ptr Word8
outPtr (Int -> Ptr Word8) -> (Int -> Int) -> Int -> Ptr Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
shareSize)) [Int
0..(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)]
Ptr (Ptr Word8) -> [Ptr Word8] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray Ptr (Ptr Word8)
sharePtrArrayPtr [Ptr Word8]
sharePtrs
HasCallStack => IO CInt -> IO ()
IO CInt -> IO ()
throwBotanIfNegative_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ CSize
-> CSize -> ConstPtr Word8 -> CSize -> Ptr (Ptr Word8) -> IO CInt
botan_zfec_encode
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
k)
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
(Ptr Word8 -> ConstPtr Word8
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr Word8
inputPtr)
CSize
inputLen
Ptr (Ptr Word8)
sharePtrArrayPtr
[ByteString]
shares <- (Ptr Word8 -> IO ByteString) -> [Ptr Word8] -> IO [ByteString]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (CStringLen -> IO ByteString
ByteString.packCStringLen (CStringLen -> IO ByteString)
-> (Ptr Word8 -> CStringLen) -> Ptr Word8 -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,Int
shareSize) (Ptr CChar -> CStringLen)
-> (Ptr Word8 -> Ptr CChar) -> Ptr Word8 -> CStringLen
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Word8 -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr) [Ptr Word8]
sharePtrs
[ZFECShare] -> IO [ZFECShare]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([ZFECShare] -> IO [ZFECShare]) -> [ZFECShare] -> IO [ZFECShare]
forall a b. NFData a => (a -> b) -> a -> b
$!! [Int] -> [ByteString] -> [ZFECShare]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)] [ByteString]
shares
zfecDecode
:: Int
-> Int
-> [ZFECShare]
-> IO ByteString
zfecDecode :: Int -> Int -> [ZFECShare] -> IO ByteString
zfecDecode Int
_ Int
_ [] = ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
""
zfecDecode Int
k Int
n shares :: [ZFECShare]
shares@((Int
_,ByteString
share0):[ZFECShare]
_) = do
Int -> (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
k ((Ptr CSize -> IO ByteString) -> IO ByteString)
-> (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \ (Ptr CSize
indexesPtr :: Ptr CSize) -> do
Ptr CSize -> [CSize] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray Ptr CSize
indexesPtr [CSize]
shareIndexes
(forall a. ByteString -> (Ptr Word8 -> IO a) -> IO a)
-> [ByteString] -> ([Ptr Word8] -> IO ByteString) -> IO ByteString
forall typ ptr b.
(forall a. typ -> (ptr -> IO a) -> IO a)
-> [typ] -> ([ptr] -> IO b) -> IO b
withPtrs ByteString -> (Ptr Word8 -> IO a) -> IO a
forall a. ByteString -> (Ptr Word8 -> IO a) -> IO a
forall byte a. ByteString -> (Ptr byte -> IO a) -> IO a
unsafeAsBytes [ByteString]
shareBytes (([Ptr Word8] -> IO ByteString) -> IO ByteString)
-> ([Ptr Word8] -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \ ([Ptr Word8]
sharePtrs :: [Ptr Word8]) -> do
Int -> (Ptr (Ptr Word8) -> IO ByteString) -> IO ByteString
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
k ((Ptr (Ptr Word8) -> IO ByteString) -> IO ByteString)
-> (Ptr (Ptr Word8) -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \ (Ptr (Ptr Word8)
sharePtrArrayPtr :: Ptr (Ptr Word8)) -> do
Ptr (Ptr Word8) -> [Ptr Word8] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray Ptr (Ptr Word8)
sharePtrArrayPtr [Ptr Word8]
sharePtrs
Int -> (Ptr Word8 -> IO ()) -> IO ByteString
forall byte. Int -> (Ptr byte -> IO ()) -> IO ByteString
allocBytes (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
shareSize) ((Ptr Word8 -> IO ()) -> IO ByteString)
-> (Ptr Word8 -> IO ()) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
outPtr -> do
Int -> (Ptr (Ptr Word8) -> IO ()) -> IO ()
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
n ((Ptr (Ptr Word8) -> IO ()) -> IO ())
-> (Ptr (Ptr Word8) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ (Ptr (Ptr Word8)
outPtrArrayPtr :: Ptr (Ptr Word8)) -> do
let outPtrs :: [Ptr Word8]
outPtrs = (Int -> Ptr Word8) -> [Int] -> [Ptr Word8]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Ptr Word8 -> Int -> Ptr Word8
forall a. Storable a => Ptr a -> Int -> Ptr a
advancePtr Ptr Word8
outPtr (Int -> Ptr Word8) -> (Int -> Int) -> Int -> Ptr Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
shareSize)) [Int
0..(Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)]
Ptr (Ptr Word8) -> [Ptr Word8] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray Ptr (Ptr Word8)
outPtrArrayPtr [Ptr Word8]
outPtrs
HasCallStack => IO CInt -> IO ()
IO CInt -> IO ()
throwBotanIfNegative_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ CSize
-> CSize
-> ConstPtr CSize
-> ConstPtr (ConstPtr Word8)
-> CSize
-> Ptr (Ptr Word8)
-> IO CInt
botan_zfec_decode
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
k)
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
(Ptr CSize -> ConstPtr CSize
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr CSize
indexesPtr)
(Ptr (ConstPtr Word8) -> ConstPtr (ConstPtr Word8)
forall a. Ptr a -> ConstPtr a
ConstPtr (Ptr (ConstPtr Word8) -> ConstPtr (ConstPtr Word8))
-> Ptr (ConstPtr Word8) -> ConstPtr (ConstPtr Word8)
forall a b. (a -> b) -> a -> b
$ Ptr (Ptr Word8) -> Ptr (ConstPtr Word8)
forall a b. Ptr a -> Ptr b
castPtr Ptr (Ptr Word8)
sharePtrArrayPtr)
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
shareSize)
Ptr (Ptr Word8)
outPtrArrayPtr
where
shareIndexes :: [CSize]
shareIndexes = (ZFECShare -> CSize) -> [ZFECShare] -> [CSize]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> (ZFECShare -> Int) -> ZFECShare -> CSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ZFECShare -> Int
forall a b. (a, b) -> a
fst) [ZFECShare]
shares
shareBytes :: [ByteString]
shareBytes = (ZFECShare -> ByteString) -> [ZFECShare] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ZFECShare -> ByteString
forall a b. (a, b) -> b
snd [ZFECShare]
shares
shareSize :: Int
shareSize = ByteString -> Int
ByteString.length ByteString
share0