{-# LANGUAGE CPP #-}
module Amazonka.Data.Body where
import qualified Amazonka.Bytes as Bytes
import Amazonka.Crypto (Digest, SHA256)
import qualified Amazonka.Crypto as Crypto
import Amazonka.Data.ByteString
import Amazonka.Data.Log
import Amazonka.Data.Query (QueryString)
import Amazonka.Data.XML (encodeXML)
import Amazonka.Lens (AReview, lens, to, un)
import Amazonka.Prelude
import Control.Monad.Trans.Resource (ResourceT, runResourceT)
import qualified Data.Aeson as Aeson
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy.Char8 as LBS8
import Data.Conduit (ConduitM, (.|))
import qualified Data.Conduit as Conduit
import qualified Data.Conduit.Binary as Conduit.Binary
import qualified Data.Text.Encoding as Text
import qualified Data.Text.Lazy.Encoding as LText
import qualified Network.HTTP.Client as Client
import qualified Network.HTTP.Conduit as Client.Conduit
import qualified System.IO as IO
import qualified Text.XML as XML
#if MIN_VERSION_aeson(2,0,0)
import Data.Aeson.KeyMap (KeyMap)
#endif
getFileSize :: MonadIO m => FilePath -> m Integer
getFileSize :: FilePath -> m Integer
getFileSize FilePath
path = IO Integer -> m Integer
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IOMode -> (Handle -> IO Integer) -> IO Integer
forall r. FilePath -> IOMode -> (Handle -> IO r) -> IO r
IO.withBinaryFile FilePath
path IOMode
IO.ReadMode Handle -> IO Integer
IO.hFileSize)
newtype ResponseBody = ResponseBody
{ ResponseBody -> ConduitM () ByteString (ResourceT IO) ()
_streamBody :: ConduitM () ByteString (ResourceT IO) ()
}
instance Show ResponseBody where
show :: ResponseBody -> FilePath
show = FilePath -> ResponseBody -> FilePath
forall a b. a -> b -> a
const FilePath
"ResponseBody { ConduitM () ByteString (ResourceT IO) () }"
fuseStream ::
ResponseBody ->
ConduitM ByteString ByteString (ResourceT IO) () ->
ResponseBody
fuseStream :: ResponseBody
-> ConduitM ByteString ByteString (ResourceT IO) () -> ResponseBody
fuseStream ResponseBody
b ConduitM ByteString ByteString (ResourceT IO) ()
f = ResponseBody
b {$sel:_streamBody:ResponseBody :: ConduitM () ByteString (ResourceT IO) ()
_streamBody = ResponseBody -> ConduitM () ByteString (ResourceT IO) ()
_streamBody ResponseBody
b ConduitM () ByteString (ResourceT IO) ()
-> ConduitM ByteString ByteString (ResourceT IO) ()
-> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM ByteString ByteString (ResourceT IO) ()
f}
sinkBody :: MonadIO m => ResponseBody -> ConduitM ByteString Void (ResourceT IO) a -> m a
sinkBody :: ResponseBody -> ConduitM ByteString Void (ResourceT IO) a -> m a
sinkBody (ResponseBody ConduitM () ByteString (ResourceT IO) ()
body) ConduitM ByteString Void (ResourceT IO) a
sink =
IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ ConduitT () Void (ResourceT IO) a -> IO a
forall (m :: * -> *) r.
MonadUnliftIO m =>
ConduitT () Void (ResourceT m) r -> m r
Conduit.runConduitRes (ConduitT () Void (ResourceT IO) a -> IO a)
-> ConduitT () Void (ResourceT IO) a -> IO a
forall a b. (a -> b) -> a -> b
$ ConduitM () ByteString (ResourceT IO) ()
body ConduitM () ByteString (ResourceT IO) ()
-> ConduitM ByteString Void (ResourceT IO) a
-> ConduitT () Void (ResourceT IO) a
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM ByteString Void (ResourceT IO) a
sink
newtype ChunkSize = ChunkSize Int
deriving stock (ChunkSize -> ChunkSize -> Bool
(ChunkSize -> ChunkSize -> Bool)
-> (ChunkSize -> ChunkSize -> Bool) -> Eq ChunkSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ChunkSize -> ChunkSize -> Bool
$c/= :: ChunkSize -> ChunkSize -> Bool
== :: ChunkSize -> ChunkSize -> Bool
$c== :: ChunkSize -> ChunkSize -> Bool
Eq, Eq ChunkSize
Eq ChunkSize
-> (ChunkSize -> ChunkSize -> Ordering)
-> (ChunkSize -> ChunkSize -> Bool)
-> (ChunkSize -> ChunkSize -> Bool)
-> (ChunkSize -> ChunkSize -> Bool)
-> (ChunkSize -> ChunkSize -> Bool)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> Ord ChunkSize
ChunkSize -> ChunkSize -> Bool
ChunkSize -> ChunkSize -> Ordering
ChunkSize -> ChunkSize -> ChunkSize
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ChunkSize -> ChunkSize -> ChunkSize
$cmin :: ChunkSize -> ChunkSize -> ChunkSize
max :: ChunkSize -> ChunkSize -> ChunkSize
$cmax :: ChunkSize -> ChunkSize -> ChunkSize
>= :: ChunkSize -> ChunkSize -> Bool
$c>= :: ChunkSize -> ChunkSize -> Bool
> :: ChunkSize -> ChunkSize -> Bool
$c> :: ChunkSize -> ChunkSize -> Bool
<= :: ChunkSize -> ChunkSize -> Bool
$c<= :: ChunkSize -> ChunkSize -> Bool
< :: ChunkSize -> ChunkSize -> Bool
$c< :: ChunkSize -> ChunkSize -> Bool
compare :: ChunkSize -> ChunkSize -> Ordering
$ccompare :: ChunkSize -> ChunkSize -> Ordering
$cp1Ord :: Eq ChunkSize
Ord, Int -> ChunkSize -> ShowS
[ChunkSize] -> ShowS
ChunkSize -> FilePath
(Int -> ChunkSize -> ShowS)
-> (ChunkSize -> FilePath)
-> ([ChunkSize] -> ShowS)
-> Show ChunkSize
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [ChunkSize] -> ShowS
$cshowList :: [ChunkSize] -> ShowS
show :: ChunkSize -> FilePath
$cshow :: ChunkSize -> FilePath
showsPrec :: Int -> ChunkSize -> ShowS
$cshowsPrec :: Int -> ChunkSize -> ShowS
Show)
deriving newtype (Int -> ChunkSize
ChunkSize -> Int
ChunkSize -> [ChunkSize]
ChunkSize -> ChunkSize
ChunkSize -> ChunkSize -> [ChunkSize]
ChunkSize -> ChunkSize -> ChunkSize -> [ChunkSize]
(ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize)
-> (Int -> ChunkSize)
-> (ChunkSize -> Int)
-> (ChunkSize -> [ChunkSize])
-> (ChunkSize -> ChunkSize -> [ChunkSize])
-> (ChunkSize -> ChunkSize -> [ChunkSize])
-> (ChunkSize -> ChunkSize -> ChunkSize -> [ChunkSize])
-> Enum ChunkSize
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: ChunkSize -> ChunkSize -> ChunkSize -> [ChunkSize]
$cenumFromThenTo :: ChunkSize -> ChunkSize -> ChunkSize -> [ChunkSize]
enumFromTo :: ChunkSize -> ChunkSize -> [ChunkSize]
$cenumFromTo :: ChunkSize -> ChunkSize -> [ChunkSize]
enumFromThen :: ChunkSize -> ChunkSize -> [ChunkSize]
$cenumFromThen :: ChunkSize -> ChunkSize -> [ChunkSize]
enumFrom :: ChunkSize -> [ChunkSize]
$cenumFrom :: ChunkSize -> [ChunkSize]
fromEnum :: ChunkSize -> Int
$cfromEnum :: ChunkSize -> Int
toEnum :: Int -> ChunkSize
$ctoEnum :: Int -> ChunkSize
pred :: ChunkSize -> ChunkSize
$cpred :: ChunkSize -> ChunkSize
succ :: ChunkSize -> ChunkSize
$csucc :: ChunkSize -> ChunkSize
Enum, Integer -> ChunkSize
ChunkSize -> ChunkSize
ChunkSize -> ChunkSize -> ChunkSize
(ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize)
-> (Integer -> ChunkSize)
-> Num ChunkSize
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> ChunkSize
$cfromInteger :: Integer -> ChunkSize
signum :: ChunkSize -> ChunkSize
$csignum :: ChunkSize -> ChunkSize
abs :: ChunkSize -> ChunkSize
$cabs :: ChunkSize -> ChunkSize
negate :: ChunkSize -> ChunkSize
$cnegate :: ChunkSize -> ChunkSize
* :: ChunkSize -> ChunkSize -> ChunkSize
$c* :: ChunkSize -> ChunkSize -> ChunkSize
- :: ChunkSize -> ChunkSize -> ChunkSize
$c- :: ChunkSize -> ChunkSize -> ChunkSize
+ :: ChunkSize -> ChunkSize -> ChunkSize
$c+ :: ChunkSize -> ChunkSize -> ChunkSize
Num, Num ChunkSize
Ord ChunkSize
Num ChunkSize
-> Ord ChunkSize -> (ChunkSize -> Rational) -> Real ChunkSize
ChunkSize -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: ChunkSize -> Rational
$ctoRational :: ChunkSize -> Rational
$cp2Real :: Ord ChunkSize
$cp1Real :: Num ChunkSize
Real, Enum ChunkSize
Real ChunkSize
Real ChunkSize
-> Enum ChunkSize
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> ChunkSize)
-> (ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize))
-> (ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize))
-> (ChunkSize -> Integer)
-> Integral ChunkSize
ChunkSize -> Integer
ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize)
ChunkSize -> ChunkSize -> ChunkSize
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: ChunkSize -> Integer
$ctoInteger :: ChunkSize -> Integer
divMod :: ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize)
$cdivMod :: ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize)
quotRem :: ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize)
$cquotRem :: ChunkSize -> ChunkSize -> (ChunkSize, ChunkSize)
mod :: ChunkSize -> ChunkSize -> ChunkSize
$cmod :: ChunkSize -> ChunkSize -> ChunkSize
div :: ChunkSize -> ChunkSize -> ChunkSize
$cdiv :: ChunkSize -> ChunkSize -> ChunkSize
rem :: ChunkSize -> ChunkSize -> ChunkSize
$crem :: ChunkSize -> ChunkSize -> ChunkSize
quot :: ChunkSize -> ChunkSize -> ChunkSize
$cquot :: ChunkSize -> ChunkSize -> ChunkSize
$cp2Integral :: Enum ChunkSize
$cp1Integral :: Real ChunkSize
Integral)
instance ToLog ChunkSize where
build :: ChunkSize -> ByteStringBuilder
build = FilePath -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build (FilePath -> ByteStringBuilder)
-> (ChunkSize -> FilePath) -> ChunkSize -> ByteStringBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChunkSize -> FilePath
forall a. Show a => a -> FilePath
show
defaultChunkSize :: ChunkSize
defaultChunkSize :: ChunkSize
defaultChunkSize = ChunkSize
128 ChunkSize -> ChunkSize -> ChunkSize
forall a. Num a => a -> a -> a
* ChunkSize
1024
data ChunkedBody = ChunkedBody
{ ChunkedBody -> ChunkSize
_chunkedSize :: ChunkSize,
ChunkedBody -> Integer
_chunkedLength :: Integer,
ChunkedBody -> ConduitM () ByteString (ResourceT IO) ()
_chunkedBody :: ConduitM () ByteString (ResourceT IO) ()
}
chunkedLength :: Lens' ChunkedBody Integer
chunkedLength :: (Integer -> f Integer) -> ChunkedBody -> f ChunkedBody
chunkedLength = (ChunkedBody -> Integer)
-> (ChunkedBody -> Integer -> ChunkedBody)
-> Lens ChunkedBody ChunkedBody Integer Integer
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens ChunkedBody -> Integer
_chunkedLength (\ChunkedBody
s Integer
a -> ChunkedBody
s {$sel:_chunkedLength:ChunkedBody :: Integer
_chunkedLength = Integer
a})
instance Show ChunkedBody where
show :: ChunkedBody -> FilePath
show ChunkedBody
c =
ByteString -> FilePath
BS8.unpack (ByteString -> FilePath)
-> (ByteStringBuilder -> ByteString)
-> ByteStringBuilder
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteStringBuilder -> ByteString
forall a. ToByteString a => a -> ByteString
toBS (ByteStringBuilder -> FilePath) -> ByteStringBuilder -> FilePath
forall a b. (a -> b) -> a -> b
$
ByteStringBuilder
"ChunkedBody { chunkSize = "
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ChunkSize -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build (ChunkedBody -> ChunkSize
_chunkedSize ChunkedBody
c)
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
"<> originalLength = "
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> Integer -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build (ChunkedBody -> Integer
_chunkedLength ChunkedBody
c)
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
"<> fullChunks = "
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> Integer -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build (ChunkedBody -> Integer
fullChunks ChunkedBody
c)
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
"<> remainderBytes = "
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> Maybe Integer -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build (ChunkedBody -> Maybe Integer
remainderBytes ChunkedBody
c)
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
"}"
fuseChunks ::
ChunkedBody ->
ConduitM ByteString ByteString (ResourceT IO) () ->
ChunkedBody
fuseChunks :: ChunkedBody
-> ConduitM ByteString ByteString (ResourceT IO) () -> ChunkedBody
fuseChunks ChunkedBody
c ConduitM ByteString ByteString (ResourceT IO) ()
f = ChunkedBody
c {$sel:_chunkedBody:ChunkedBody :: ConduitM () ByteString (ResourceT IO) ()
_chunkedBody = ChunkedBody -> ConduitM () ByteString (ResourceT IO) ()
_chunkedBody ChunkedBody
c ConduitM () ByteString (ResourceT IO) ()
-> ConduitM ByteString ByteString (ResourceT IO) ()
-> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM ByteString ByteString (ResourceT IO) ()
f}
fullChunks :: ChunkedBody -> Integer
fullChunks :: ChunkedBody -> Integer
fullChunks ChunkedBody
c = ChunkedBody -> Integer
_chunkedLength ChunkedBody
c Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` ChunkSize -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ChunkedBody -> ChunkSize
_chunkedSize ChunkedBody
c)
remainderBytes :: ChunkedBody -> Maybe Integer
remainderBytes :: ChunkedBody -> Maybe Integer
remainderBytes ChunkedBody
c =
case ChunkedBody -> Integer
_chunkedLength ChunkedBody
c Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` ChunkSize -> Integer
forall a. Integral a => a -> Integer
toInteger (ChunkedBody -> ChunkSize
_chunkedSize ChunkedBody
c) of
Integer
0 -> Maybe Integer
forall a. Maybe a
Nothing
Integer
n -> Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
n
chunkedFile :: MonadIO m => ChunkSize -> FilePath -> m RequestBody
chunkedFile :: ChunkSize -> FilePath -> m RequestBody
chunkedFile ChunkSize
chunk FilePath
path = do
Integer
size <- FilePath -> m Integer
forall (m :: * -> *). MonadIO m => FilePath -> m Integer
getFileSize FilePath
path
if Integer
size Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> ChunkSize -> Integer
forall a. Integral a => a -> Integer
toInteger ChunkSize
chunk
then RequestBody -> m RequestBody
forall (m :: * -> *) a. Monad m => a -> m a
return (RequestBody -> m RequestBody) -> RequestBody -> m RequestBody
forall a b. (a -> b) -> a -> b
$ ChunkSize
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> RequestBody
unsafeChunkedBody ChunkSize
chunk Integer
size (ChunkSize -> FilePath -> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *).
MonadResource m =>
ChunkSize -> FilePath -> ConduitM () ByteString m ()
sourceFileChunks ChunkSize
chunk FilePath
path)
else HashedBody -> RequestBody
Hashed (HashedBody -> RequestBody) -> m HashedBody -> m RequestBody
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> m HashedBody
forall (m :: * -> *). MonadIO m => FilePath -> m HashedBody
hashedFile FilePath
path
chunkedFileRange ::
MonadIO m =>
ChunkSize ->
FilePath ->
Integer ->
Integer ->
m RequestBody
chunkedFileRange :: ChunkSize -> FilePath -> Integer -> Integer -> m RequestBody
chunkedFileRange ChunkSize
chunk FilePath
path Integer
offset Integer
len = do
Integer
size <- FilePath -> m Integer
forall (m :: * -> *). MonadIO m => FilePath -> m Integer
getFileSize FilePath
path
let n :: Integer
n = Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
min (Integer
size Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
offset) Integer
len
if Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> ChunkSize -> Integer
forall a. Integral a => a -> Integer
toInteger ChunkSize
chunk
then RequestBody -> m RequestBody
forall (m :: * -> *) a. Monad m => a -> m a
return (RequestBody -> m RequestBody) -> RequestBody -> m RequestBody
forall a b. (a -> b) -> a -> b
$ ChunkSize
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> RequestBody
unsafeChunkedBody ChunkSize
chunk Integer
n (ChunkSize
-> FilePath
-> Integer
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *).
MonadResource m =>
ChunkSize
-> FilePath -> Integer -> Integer -> ConduitM () ByteString m ()
sourceFileRangeChunks ChunkSize
chunk FilePath
path Integer
offset Integer
len)
else HashedBody -> RequestBody
Hashed (HashedBody -> RequestBody) -> m HashedBody -> m RequestBody
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> Integer -> Integer -> m HashedBody
forall (m :: * -> *).
MonadIO m =>
FilePath -> Integer -> Integer -> m HashedBody
hashedFileRange FilePath
path Integer
offset Integer
len
unsafeChunkedBody ::
ChunkSize ->
Integer ->
ConduitM () ByteString (ResourceT IO) () ->
RequestBody
unsafeChunkedBody :: ChunkSize
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> RequestBody
unsafeChunkedBody ChunkSize
chunk Integer
size = ChunkedBody -> RequestBody
Chunked (ChunkedBody -> RequestBody)
-> (ConduitM () ByteString (ResourceT IO) () -> ChunkedBody)
-> ConduitM () ByteString (ResourceT IO) ()
-> RequestBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChunkSize
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> ChunkedBody
ChunkedBody ChunkSize
chunk Integer
size
sourceFileChunks ::
MonadResource m =>
ChunkSize ->
FilePath ->
ConduitM () ByteString m ()
sourceFileChunks :: ChunkSize -> FilePath -> ConduitM () ByteString m ()
sourceFileChunks (ChunkSize Int
chunk) FilePath
path =
IO Handle
-> (Handle -> IO ())
-> (Handle -> ConduitM () ByteString m ())
-> ConduitM () ByteString m ()
forall (m :: * -> *) a i o r.
MonadResource m =>
IO a -> (a -> IO ()) -> (a -> ConduitT i o m r) -> ConduitT i o m r
Conduit.bracketP (FilePath -> IOMode -> IO Handle
IO.openBinaryFile FilePath
path IOMode
IO.ReadMode) Handle -> IO ()
IO.hClose Handle -> ConduitM () ByteString m ()
go
where
go :: Handle -> ConduitM () ByteString m ()
go Handle
hd = do
ByteString
bs <- IO ByteString -> ConduitT () ByteString m ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Int -> IO ByteString
BS.hGet Handle
hd Int
chunk)
Bool -> ConduitM () ByteString m () -> ConduitM () ByteString m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
BS.null ByteString
bs) (ConduitM () ByteString m () -> ConduitM () ByteString m ())
-> ConduitM () ByteString m () -> ConduitM () ByteString m ()
forall a b. (a -> b) -> a -> b
$ do
ByteString -> ConduitM () ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
Conduit.yield ByteString
bs
Handle -> ConduitM () ByteString m ()
go Handle
hd
sourceFileRangeChunks ::
MonadResource m =>
ChunkSize ->
FilePath ->
Integer ->
Integer ->
ConduitM () ByteString m ()
sourceFileRangeChunks :: ChunkSize
-> FilePath -> Integer -> Integer -> ConduitM () ByteString m ()
sourceFileRangeChunks (ChunkSize Int
chunk) FilePath
path Integer
offset Integer
len =
IO Handle
-> (Handle -> IO ())
-> (Handle -> ConduitM () ByteString m ())
-> ConduitM () ByteString m ()
forall (m :: * -> *) a i o r.
MonadResource m =>
IO a -> (a -> IO ()) -> (a -> ConduitT i o m r) -> ConduitT i o m r
Conduit.bracketP IO Handle
acquire Handle -> IO ()
IO.hClose Handle -> ConduitM () ByteString m ()
seek
where
acquire :: IO Handle
acquire = FilePath -> IOMode -> IO Handle
IO.openBinaryFile FilePath
path IOMode
IO.ReadMode
seek :: Handle -> ConduitM () ByteString m ()
seek Handle
hd = do
IO () -> ConduitM () ByteString m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> SeekMode -> Integer -> IO ()
IO.hSeek Handle
hd SeekMode
IO.AbsoluteSeek Integer
offset)
Int -> Handle -> ConduitM () ByteString m ()
go (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
len) Handle
hd
go :: Int -> Handle -> ConduitM () ByteString m ()
go Int
remainder Handle
hd
| Int
remainder Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
chunk = do
ByteString
bs <- IO ByteString -> ConduitT () ByteString m ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Int -> IO ByteString
BS.hGet Handle
hd Int
remainder)
Bool -> ConduitM () ByteString m () -> ConduitM () ByteString m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
BS.null ByteString
bs) (ConduitM () ByteString m () -> ConduitM () ByteString m ())
-> ConduitM () ByteString m () -> ConduitM () ByteString m ()
forall a b. (a -> b) -> a -> b
$
ByteString -> ConduitM () ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
Conduit.yield ByteString
bs
| Bool
otherwise = do
ByteString
bs <- IO ByteString -> ConduitT () ByteString m ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Int -> IO ByteString
BS.hGet Handle
hd Int
chunk)
Bool -> ConduitM () ByteString m () -> ConduitM () ByteString m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
BS.null ByteString
bs) (ConduitM () ByteString m () -> ConduitM () ByteString m ())
-> ConduitM () ByteString m () -> ConduitM () ByteString m ()
forall a b. (a -> b) -> a -> b
$ do
ByteString -> ConduitM () ByteString m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
Conduit.yield ByteString
bs
Int -> Handle -> ConduitM () ByteString m ()
go (Int
remainder Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
chunk) Handle
hd
data HashedBody
= HashedStream (Digest SHA256) !Integer (ConduitM () ByteString (ResourceT IO) ())
| HashedBytes (Digest SHA256) ByteString
instance Show HashedBody where
show :: HashedBody -> FilePath
show = \case
HashedStream Digest SHA256
h Integer
n ConduitM () ByteString (ResourceT IO) ()
_ -> ByteStringBuilder -> Digest SHA256 -> Integer -> FilePath
forall a a.
(ByteArrayAccess a, ToLog a) =>
ByteStringBuilder -> a -> a -> FilePath
str ByteStringBuilder
"HashedStream" Digest SHA256
h Integer
n
HashedBytes Digest SHA256
h ByteString
x -> ByteStringBuilder -> Digest SHA256 -> Int -> FilePath
forall a a.
(ByteArrayAccess a, ToLog a) =>
ByteStringBuilder -> a -> a -> FilePath
str ByteStringBuilder
"HashedBody" Digest SHA256
h (ByteString -> Int
BS.length ByteString
x)
where
str :: ByteStringBuilder -> a -> a -> FilePath
str ByteStringBuilder
c a
h a
n =
ByteString -> FilePath
BS8.unpack (ByteString -> FilePath)
-> (ByteStringBuilder -> ByteString)
-> ByteStringBuilder
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteStringBuilder -> ByteString
forall a. ToByteString a => a -> ByteString
toBS (ByteStringBuilder -> FilePath) -> ByteStringBuilder -> FilePath
forall a b. (a -> b) -> a -> b
$
ByteStringBuilder
c ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
" { sha256 = "
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteString -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build (a -> ByteString
forall a. ByteArrayAccess a => a -> ByteString
Bytes.encodeBase16 a
h)
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
", length = "
ByteStringBuilder -> ByteStringBuilder -> ByteStringBuilder
forall a. Semigroup a => a -> a -> a
<> a -> ByteStringBuilder
forall a. ToLog a => a -> ByteStringBuilder
build a
n
instance IsString HashedBody where
fromString :: FilePath -> HashedBody
fromString = FilePath -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed
sha256Base16 :: HashedBody -> ByteString
sha256Base16 :: HashedBody -> ByteString
sha256Base16 =
Digest SHA256 -> ByteString
forall a. ByteArrayAccess a => a -> ByteString
Bytes.encodeBase16 (Digest SHA256 -> ByteString)
-> (HashedBody -> Digest SHA256) -> HashedBody -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
HashedStream Digest SHA256
h Integer
_ ConduitM () ByteString (ResourceT IO) ()
_ -> Digest SHA256
h
HashedBytes Digest SHA256
h ByteString
_ -> Digest SHA256
h
hashedFile ::
MonadIO m =>
FilePath ->
m HashedBody
hashedFile :: FilePath -> m HashedBody
hashedFile FilePath
path =
IO HashedBody -> m HashedBody
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HashedBody -> m HashedBody) -> IO HashedBody -> m HashedBody
forall a b. (a -> b) -> a -> b
$
Digest SHA256
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> HashedBody
HashedStream
(Digest SHA256
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> HashedBody)
-> IO (Digest SHA256)
-> IO
(Integer -> ConduitM () ByteString (ResourceT IO) () -> HashedBody)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ResourceT IO (Digest SHA256) -> IO (Digest SHA256)
forall (m :: * -> *) a. MonadUnliftIO m => ResourceT m a -> m a
runResourceT (FilePath -> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) i.
MonadResource m =>
FilePath -> ConduitT i ByteString m ()
Conduit.Binary.sourceFile FilePath
path ConduitM () ByteString (ResourceT IO) ()
-> ConduitT ByteString Void (ResourceT IO) (Digest SHA256)
-> ResourceT IO (Digest SHA256)
forall (m :: * -> *) a r.
Monad m =>
ConduitT () a m () -> ConduitT a Void m r -> m r
`Conduit.connect` ConduitT ByteString Void (ResourceT IO) (Digest SHA256)
forall (m :: * -> *) o.
Monad m =>
ConduitM ByteString o m (Digest SHA256)
Crypto.sinkSHA256)
IO
(Integer -> ConduitM () ByteString (ResourceT IO) () -> HashedBody)
-> IO Integer
-> IO (ConduitM () ByteString (ResourceT IO) () -> HashedBody)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> FilePath -> IO Integer
forall (m :: * -> *). MonadIO m => FilePath -> m Integer
getFileSize FilePath
path
IO (ConduitM () ByteString (ResourceT IO) () -> HashedBody)
-> IO (ConduitM () ByteString (ResourceT IO) ()) -> IO HashedBody
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ConduitM () ByteString (ResourceT IO) ()
-> IO (ConduitM () ByteString (ResourceT IO) ())
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath -> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) i.
MonadResource m =>
FilePath -> ConduitT i ByteString m ()
Conduit.Binary.sourceFile FilePath
path)
hashedFileRange ::
MonadIO m =>
FilePath ->
Integer ->
Integer ->
m HashedBody
hashedFileRange :: FilePath -> Integer -> Integer -> m HashedBody
hashedFileRange FilePath
path (Integer -> Maybe Integer
forall a. a -> Maybe a
Just -> Maybe Integer
offset) (Integer -> Maybe Integer
forall a. a -> Maybe a
Just -> Maybe Integer
len) =
IO HashedBody -> m HashedBody
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HashedBody -> m HashedBody) -> IO HashedBody -> m HashedBody
forall a b. (a -> b) -> a -> b
$
Digest SHA256
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> HashedBody
HashedStream
(Digest SHA256
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> HashedBody)
-> IO (Digest SHA256)
-> IO
(Integer -> ConduitM () ByteString (ResourceT IO) () -> HashedBody)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ResourceT IO (Digest SHA256) -> IO (Digest SHA256)
forall (m :: * -> *) a. MonadUnliftIO m => ResourceT m a -> m a
runResourceT (FilePath
-> Maybe Integer
-> Maybe Integer
-> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) i.
MonadResource m =>
FilePath
-> Maybe Integer -> Maybe Integer -> ConduitT i ByteString m ()
Conduit.Binary.sourceFileRange FilePath
path Maybe Integer
offset Maybe Integer
len ConduitM () ByteString (ResourceT IO) ()
-> ConduitT ByteString Void (ResourceT IO) (Digest SHA256)
-> ResourceT IO (Digest SHA256)
forall (m :: * -> *) a r.
Monad m =>
ConduitT () a m () -> ConduitT a Void m r -> m r
`Conduit.connect` ConduitT ByteString Void (ResourceT IO) (Digest SHA256)
forall (m :: * -> *) o.
Monad m =>
ConduitM ByteString o m (Digest SHA256)
Crypto.sinkSHA256)
IO
(Integer -> ConduitM () ByteString (ResourceT IO) () -> HashedBody)
-> IO Integer
-> IO (ConduitM () ByteString (ResourceT IO) () -> HashedBody)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> FilePath -> IO Integer
forall (m :: * -> *). MonadIO m => FilePath -> m Integer
getFileSize FilePath
path
IO (ConduitM () ByteString (ResourceT IO) () -> HashedBody)
-> IO (ConduitM () ByteString (ResourceT IO) ()) -> IO HashedBody
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ConduitM () ByteString (ResourceT IO) ()
-> IO (ConduitM () ByteString (ResourceT IO) ())
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath
-> Maybe Integer
-> Maybe Integer
-> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) i.
MonadResource m =>
FilePath
-> Maybe Integer -> Maybe Integer -> ConduitT i ByteString m ()
Conduit.Binary.sourceFileRange FilePath
path Maybe Integer
offset Maybe Integer
len)
hashedBody ::
Crypto.Digest Crypto.SHA256 ->
Integer ->
ConduitM () ByteString (ResourceT IO) () ->
HashedBody
hashedBody :: Digest SHA256
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> HashedBody
hashedBody = Digest SHA256
-> Integer
-> ConduitM () ByteString (ResourceT IO) ()
-> HashedBody
HashedStream
data RequestBody
= Chunked ChunkedBody
| Hashed HashedBody
deriving stock (Int -> RequestBody -> ShowS
[RequestBody] -> ShowS
RequestBody -> FilePath
(Int -> RequestBody -> ShowS)
-> (RequestBody -> FilePath)
-> ([RequestBody] -> ShowS)
-> Show RequestBody
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [RequestBody] -> ShowS
$cshowList :: [RequestBody] -> ShowS
show :: RequestBody -> FilePath
$cshow :: RequestBody -> FilePath
showsPrec :: Int -> RequestBody -> ShowS
$cshowsPrec :: Int -> RequestBody -> ShowS
Show)
instance IsString RequestBody where
fromString :: FilePath -> RequestBody
fromString = HashedBody -> RequestBody
Hashed (HashedBody -> RequestBody)
-> (FilePath -> HashedBody) -> FilePath -> RequestBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> HashedBody
forall a. IsString a => FilePath -> a
fromString
md5Base64 :: RequestBody -> Maybe ByteString
md5Base64 :: RequestBody -> Maybe ByteString
md5Base64 = \case
Hashed (HashedBytes Digest SHA256
_ ByteString
x) -> ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (Digest MD5 -> ByteString
forall a. ByteArrayAccess a => a -> ByteString
Bytes.encodeBase64 (ByteString -> Digest MD5
forall a. ByteArrayAccess a => a -> Digest MD5
Crypto.hashMD5 ByteString
x))
RequestBody
_ -> Maybe ByteString
forall a. Maybe a
Nothing
isStreaming :: RequestBody -> Bool
isStreaming :: RequestBody -> Bool
isStreaming = \case
Hashed (HashedStream {}) -> Bool
True
RequestBody
_ -> Bool
False
toRequestBody :: RequestBody -> Client.RequestBody
toRequestBody :: RequestBody -> RequestBody
toRequestBody = \case
Chunked ChunkedBody
x -> ConduitM () ByteString (ResourceT IO) () -> RequestBody
Client.Conduit.requestBodySourceChunked (ChunkedBody -> ConduitM () ByteString (ResourceT IO) ()
_chunkedBody ChunkedBody
x)
Hashed HashedBody
x -> case HashedBody
x of
HashedStream Digest SHA256
_ Integer
n ConduitM () ByteString (ResourceT IO) ()
f -> Int64 -> ConduitM () ByteString (ResourceT IO) () -> RequestBody
Client.Conduit.requestBodySource (Integer -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n) ConduitM () ByteString (ResourceT IO) ()
f
HashedBytes Digest SHA256
_ ByteString
b -> ByteString -> RequestBody
Client.RequestBodyBS ByteString
b
contentLength :: RequestBody -> Integer
contentLength :: RequestBody -> Integer
contentLength = \case
Chunked ChunkedBody
x -> ChunkedBody -> Integer
_chunkedLength ChunkedBody
x
Hashed HashedBody
x -> case HashedBody
x of
HashedStream Digest SHA256
_ Integer
n ConduitM () ByteString (ResourceT IO) ()
_ -> Integer
n
HashedBytes Digest SHA256
_ ByteString
b -> Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
BS.length ByteString
b)
class ToHashedBody a where
toHashed :: a -> HashedBody
instance ToHashedBody ByteString where
toHashed :: ByteString -> HashedBody
toHashed ByteString
x = Digest SHA256 -> ByteString -> HashedBody
HashedBytes (ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Crypto.hash ByteString
x) ByteString
x
instance ToHashedBody HashedBody where
toHashed :: HashedBody -> HashedBody
toHashed = HashedBody -> HashedBody
forall a. a -> a
id
instance ToHashedBody String where
toHashed :: FilePath -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (FilePath -> ByteString) -> FilePath -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> ByteString
LBS8.pack
instance ToHashedBody ByteStringLazy where
toHashed :: ByteString -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (ByteString -> ByteString) -> ByteString -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
forall a. ToByteString a => a -> ByteString
toBS
instance ToHashedBody Text where
toHashed :: Text -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (Text -> ByteString) -> Text -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8
instance ToHashedBody TextLazy where
toHashed :: TextLazy -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (TextLazy -> ByteString) -> TextLazy -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextLazy -> ByteString
LText.encodeUtf8
instance ToHashedBody Aeson.Value where
toHashed :: Value -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (Value -> ByteString) -> Value -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> ByteString
forall a. ToJSON a => a -> ByteString
Aeson.encode
instance ToHashedBody XML.Element where
toHashed :: Element -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (Element -> ByteString) -> Element -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> ByteString
forall a. ToElement a => a -> ByteString
encodeXML
instance ToHashedBody QueryString where
toHashed :: QueryString -> HashedBody
toHashed = ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (ByteString -> HashedBody)
-> (QueryString -> ByteString) -> QueryString -> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryString -> ByteString
forall a. ToByteString a => a -> ByteString
toBS
#if MIN_VERSION_aeson(2,0,0)
instance ToHashedBody (KeyMap Aeson.Value) where
toHashed = toHashed . Aeson.Object
#else
instance ToHashedBody (HashMap Text Aeson.Value) where
toHashed :: HashMap Text Value -> HashedBody
toHashed = Value -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed (Value -> HashedBody)
-> (HashMap Text Value -> Value)
-> HashMap Text Value
-> HashedBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashMap Text Value -> Value
Aeson.Object
#endif
class ToBody a where
toBody :: a -> RequestBody
default toBody :: ToHashedBody a => a -> RequestBody
toBody = HashedBody -> RequestBody
Hashed (HashedBody -> RequestBody)
-> (a -> HashedBody) -> a -> RequestBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed
instance ToBody RequestBody where
toBody :: RequestBody -> RequestBody
toBody = RequestBody -> RequestBody
forall a. a -> a
id
instance ToBody HashedBody where
toBody :: HashedBody -> RequestBody
toBody = HashedBody -> RequestBody
Hashed
instance ToBody ChunkedBody where
toBody :: ChunkedBody -> RequestBody
toBody = ChunkedBody -> RequestBody
Chunked
instance ToHashedBody a => ToBody (Maybe a) where
toBody :: Maybe a -> RequestBody
toBody = HashedBody -> RequestBody
Hashed (HashedBody -> RequestBody)
-> (Maybe a -> HashedBody) -> Maybe a -> RequestBody
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashedBody -> (a -> HashedBody) -> Maybe a -> HashedBody
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ByteString -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed ByteString
BS.empty) a -> HashedBody
forall a. ToHashedBody a => a -> HashedBody
toHashed
instance ToBody String
instance ToBody ByteStringLazy
instance ToBody ByteString
instance ToBody Text
instance ToBody TextLazy
#if MIN_VERSION_aeson(2,0,0)
instance ToBody (KeyMap Aeson.Value)
#else
instance ToBody (HashMap Text Aeson.Value)
#endif
instance ToBody Aeson.Value
instance ToBody XML.Element
instance ToBody QueryString
_Body :: ToBody a => AReview RequestBody a
_Body :: AReview RequestBody a
_Body = Getting RequestBody a RequestBody -> AReview RequestBody a
forall (p :: * -> * -> *) (f :: * -> *) a s.
(Profunctor p, Bifunctor p, Functor f) =>
Getting a s a -> Optic' p f a s
un ((a -> RequestBody) -> Getting RequestBody a RequestBody
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to a -> RequestBody
forall a. ToBody a => a -> RequestBody
toBody)