{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_HADDOCK not-home #-}
module Servant.API.Stream (
Stream,
StreamGet,
StreamPost,
StreamBody,
StreamBody',
SourceIO,
ToSourceIO (..),
FromSourceIO (..),
SourceToSourceIO (..),
FramingRender (..),
FramingUnrender (..),
NoFraming,
NewlineFraming,
NetstringFraming,
) where
import Control.Applicative
((<|>))
import Control.Monad.IO.Class
(MonadIO (..))
import qualified Data.Attoparsec.ByteString as A
import qualified Data.Attoparsec.ByteString.Char8 as A8
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Char8 as LBS8
import Data.List.NonEmpty
(NonEmpty (..))
import Data.Monoid
((<>))
import Data.Proxy
(Proxy)
import Data.Typeable
(Typeable)
import GHC.Generics
(Generic)
import GHC.TypeLits
(Nat)
import Network.HTTP.Types.Method
(StdMethod (..))
import Servant.Types.SourceT
data Stream (method :: k1) (status :: Nat) (framing :: *) (contentType :: *) (a :: *)
deriving (Typeable, (forall x.
Stream method status framing contentType a
-> Rep (Stream method status framing contentType a) x)
-> (forall x.
Rep (Stream method status framing contentType a) x
-> Stream method status framing contentType a)
-> Generic (Stream method status framing contentType a)
forall x.
Rep (Stream method status framing contentType a) x
-> Stream method status framing contentType a
forall x.
Stream method status framing contentType a
-> Rep (Stream method status framing contentType a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall k1 (method :: k1) (status :: Nat) framing contentType a x.
Rep (Stream method status framing contentType a) x
-> Stream method status framing contentType a
forall k1 (method :: k1) (status :: Nat) framing contentType a x.
Stream method status framing contentType a
-> Rep (Stream method status framing contentType a) x
$cto :: forall k1 (method :: k1) (status :: Nat) framing contentType a x.
Rep (Stream method status framing contentType a) x
-> Stream method status framing contentType a
$cfrom :: forall k1 (method :: k1) (status :: Nat) framing contentType a x.
Stream method status framing contentType a
-> Rep (Stream method status framing contentType a) x
Generic)
type StreamGet = Stream 'GET 200
type StreamPost = Stream 'POST 200
type StreamBody = StreamBody' '[]
data StreamBody' (mods :: [*]) (framing :: *) (contentType :: *) (a :: *)
deriving (Typeable, (forall x.
StreamBody' mods framing contentType a
-> Rep (StreamBody' mods framing contentType a) x)
-> (forall x.
Rep (StreamBody' mods framing contentType a) x
-> StreamBody' mods framing contentType a)
-> Generic (StreamBody' mods framing contentType a)
forall (mods :: [*]) framing contentType a x.
Rep (StreamBody' mods framing contentType a) x
-> StreamBody' mods framing contentType a
forall (mods :: [*]) framing contentType a x.
StreamBody' mods framing contentType a
-> Rep (StreamBody' mods framing contentType a) x
forall x.
Rep (StreamBody' mods framing contentType a) x
-> StreamBody' mods framing contentType a
forall x.
StreamBody' mods framing contentType a
-> Rep (StreamBody' mods framing contentType a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall (mods :: [*]) framing contentType a x.
Rep (StreamBody' mods framing contentType a) x
-> StreamBody' mods framing contentType a
$cfrom :: forall (mods :: [*]) framing contentType a x.
StreamBody' mods framing contentType a
-> Rep (StreamBody' mods framing contentType a) x
Generic)
type SourceIO = SourceT IO
class ToSourceIO chunk a | a -> chunk where
toSourceIO :: a -> SourceIO chunk
class SourceToSourceIO m where
sourceToSourceIO :: SourceT m a -> SourceT IO a
instance SourceToSourceIO IO where
sourceToSourceIO :: SourceT IO a -> SourceT IO a
sourceToSourceIO = SourceT IO a -> SourceT IO a
forall a. a -> a
id
instance SourceToSourceIO m => ToSourceIO chunk (SourceT m chunk) where
toSourceIO :: SourceT m chunk -> SourceIO chunk
toSourceIO = SourceT m chunk -> SourceIO chunk
forall (m :: * -> *) a.
SourceToSourceIO m =>
SourceT m a -> SourceT IO a
sourceToSourceIO
instance ToSourceIO a (NonEmpty a) where
toSourceIO :: NonEmpty a -> SourceIO a
toSourceIO (a
x :| [a]
xs) = StepT IO a -> SourceIO a
forall (m :: * -> *) a. StepT m a -> SourceT m a
fromStepT (a -> StepT IO a -> StepT IO a
forall (m :: * -> *) a. a -> StepT m a -> StepT m a
Yield a
x ((a -> StepT IO a -> StepT IO a) -> StepT IO a -> [a] -> StepT IO a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> StepT IO a -> StepT IO a
forall (m :: * -> *) a. a -> StepT m a -> StepT m a
Yield StepT IO a
forall (m :: * -> *) a. StepT m a
Stop [a]
xs))
instance ToSourceIO a [a] where
toSourceIO :: [a] -> SourceIO a
toSourceIO = [a] -> SourceIO a
forall a (m :: * -> *). [a] -> SourceT m a
source
class FromSourceIO chunk a | a -> chunk where
fromSourceIO :: SourceIO chunk -> a
instance MonadIO m => FromSourceIO a (SourceT m a) where
fromSourceIO :: SourceIO a -> SourceT m a
fromSourceIO = SourceIO a -> SourceT m a
forall (m :: * -> *) a. MonadIO m => SourceIO a -> SourceT m a
sourceFromSourceIO
sourceFromSourceIO :: forall m a. MonadIO m => SourceT IO a -> SourceT m a
sourceFromSourceIO :: SourceT IO a -> SourceT m a
sourceFromSourceIO SourceT IO a
src =
(forall b. (StepT m a -> m b) -> m b) -> SourceT m a
forall (m :: * -> *) a.
(forall b. (StepT m a -> m b) -> m b) -> SourceT m a
SourceT ((forall b. (StepT m a -> m b) -> m b) -> SourceT m a)
-> (forall b. (StepT m a -> m b) -> m b) -> SourceT m a
forall a b. (a -> b) -> a -> b
$ \StepT m a -> m b
k ->
StepT m a -> m b
k (StepT m a -> m b) -> StepT m a -> m b
forall a b. (a -> b) -> a -> b
$ m (StepT m a) -> StepT m a
forall (m :: * -> *) a. m (StepT m a) -> StepT m a
Effect (m (StepT m a) -> StepT m a) -> m (StepT m a) -> StepT m a
forall a b. (a -> b) -> a -> b
$ IO (StepT m a) -> m (StepT m a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (StepT m a) -> m (StepT m a))
-> IO (StepT m a) -> m (StepT m a)
forall a b. (a -> b) -> a -> b
$ SourceT IO a -> (StepT IO a -> IO (StepT m a)) -> IO (StepT m a)
forall (m :: * -> *) a.
SourceT m a -> forall b. (StepT m a -> m b) -> m b
unSourceT SourceT IO a
src (StepT m a -> IO (StepT m a)
forall (m :: * -> *) a. Monad m => a -> m a
return (StepT m a -> IO (StepT m a))
-> (StepT IO a -> StepT m a) -> StepT IO a -> IO (StepT m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StepT IO a -> StepT m a
go)
where
go :: StepT IO a -> StepT m a
go :: StepT IO a -> StepT m a
go StepT IO a
Stop = StepT m a
forall (m :: * -> *) a. StepT m a
Stop
go (Error String
err) = String -> StepT m a
forall (m :: * -> *) a. String -> StepT m a
Error String
err
go (Skip StepT IO a
s) = StepT m a -> StepT m a
forall (m :: * -> *) a. StepT m a -> StepT m a
Skip (StepT IO a -> StepT m a
go StepT IO a
s)
go (Effect IO (StepT IO a)
ms) = m (StepT m a) -> StepT m a
forall (m :: * -> *) a. m (StepT m a) -> StepT m a
Effect (IO (StepT m a) -> m (StepT m a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO ((StepT IO a -> StepT m a) -> IO (StepT IO a) -> IO (StepT m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap StepT IO a -> StepT m a
go IO (StepT IO a)
ms))
go (Yield a
x StepT IO a
s) = a -> StepT m a -> StepT m a
forall (m :: * -> *) a. a -> StepT m a -> StepT m a
Yield a
x (StepT IO a -> StepT m a
go StepT IO a
s)
{-# NOINLINE [2] sourceFromSourceIO #-}
{-# RULES "sourceFromSourceIO @IO" sourceFromSourceIO = id :: SourceT IO a -> SourceT IO a #-}
class FramingRender strategy where
framingRender :: Monad m => Proxy strategy -> (a -> LBS.ByteString) -> SourceT m a -> SourceT m LBS.ByteString
class FramingUnrender strategy where
framingUnrender :: Monad m => Proxy strategy -> (LBS.ByteString -> Either String a) -> SourceT m BS.ByteString -> SourceT m a
data NoFraming
instance FramingRender NoFraming where
framingRender :: Proxy NoFraming
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
framingRender Proxy NoFraming
_ = (a -> ByteString) -> SourceT m a -> SourceT m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
instance FramingUnrender NoFraming where
framingUnrender :: Proxy NoFraming
-> (ByteString -> Either String a)
-> SourceT m ByteString
-> SourceT m a
framingUnrender Proxy NoFraming
_ ByteString -> Either String a
f = (StepT m ByteString -> StepT m a)
-> SourceT m ByteString -> SourceT m a
forall (m :: * -> *) a b.
(StepT m a -> StepT m b) -> SourceT m a -> SourceT m b
mapStepT StepT m ByteString -> StepT m a
forall (m :: * -> *). Functor m => StepT m ByteString -> StepT m a
go
where
go :: StepT m ByteString -> StepT m a
go StepT m ByteString
Stop = StepT m a
forall (m :: * -> *) a. StepT m a
Stop
go (Error String
err) = String -> StepT m a
forall (m :: * -> *) a. String -> StepT m a
Error String
err
go (Skip StepT m ByteString
s) = StepT m a -> StepT m a
forall (m :: * -> *) a. StepT m a -> StepT m a
Skip (StepT m ByteString -> StepT m a
go StepT m ByteString
s)
go (Effect m (StepT m ByteString)
ms) = m (StepT m a) -> StepT m a
forall (m :: * -> *) a. m (StepT m a) -> StepT m a
Effect ((StepT m ByteString -> StepT m a)
-> m (StepT m ByteString) -> m (StepT m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap StepT m ByteString -> StepT m a
go m (StepT m ByteString)
ms)
go (Yield ByteString
x StepT m ByteString
s) = case ByteString -> Either String a
f (ByteString -> ByteString
LBS.fromStrict ByteString
x) of
Right a
y -> a -> StepT m a -> StepT m a
forall (m :: * -> *) a. a -> StepT m a -> StepT m a
Yield a
y (StepT m ByteString -> StepT m a
go StepT m ByteString
s)
Left String
err -> String -> StepT m a
forall (m :: * -> *) a. String -> StepT m a
Error String
err
data NewlineFraming
instance FramingRender NewlineFraming where
framingRender :: Proxy NewlineFraming
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
framingRender Proxy NewlineFraming
_ a -> ByteString
f = (a -> ByteString) -> SourceT m a -> SourceT m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a
x -> a -> ByteString
f a
x ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"\n")
instance FramingUnrender NewlineFraming where
framingUnrender :: Proxy NewlineFraming
-> (ByteString -> Either String a)
-> SourceT m ByteString
-> SourceT m a
framingUnrender Proxy NewlineFraming
_ ByteString -> Either String a
f = Parser a -> SourceT m ByteString -> SourceT m a
forall (m :: * -> *) a.
Monad m =>
Parser a -> SourceT m ByteString -> SourceT m a
transformWithAtto (Parser a -> SourceT m ByteString -> SourceT m a)
-> Parser a -> SourceT m ByteString -> SourceT m a
forall a b. (a -> b) -> a -> b
$ do
ByteString
bs <- (Word8 -> Bool) -> Parser ByteString
A.takeWhile (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
10)
() () -> Parser ByteString Word8 -> Parser ByteString ()
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Word8 -> Parser ByteString Word8
A.word8 Word8
10 Parser ByteString ()
-> Parser ByteString () -> Parser ByteString ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString ()
forall t. Chunk t => Parser t ()
A.endOfInput
(String -> Parser a)
-> (a -> Parser a) -> Either String a -> Parser a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either String a
f (ByteString -> ByteString
LBS.fromStrict ByteString
bs))
data NetstringFraming
instance FramingRender NetstringFraming where
framingRender :: Proxy NetstringFraming
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
framingRender Proxy NetstringFraming
_ a -> ByteString
f = (a -> ByteString) -> SourceT m a -> SourceT m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> ByteString) -> SourceT m a -> SourceT m ByteString)
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
forall a b. (a -> b) -> a -> b
$ \a
x ->
let bs :: ByteString
bs = a -> ByteString
f a
x
in String -> ByteString
LBS8.pack (Int64 -> String
forall a. Show a => a -> String
show (ByteString -> Int64
LBS8.length ByteString
bs)) ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
":" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
bs ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
","
instance FramingUnrender NetstringFraming where
framingUnrender :: Proxy NetstringFraming
-> (ByteString -> Either String a)
-> SourceT m ByteString
-> SourceT m a
framingUnrender Proxy NetstringFraming
_ ByteString -> Either String a
f = Parser a -> SourceT m ByteString -> SourceT m a
forall (m :: * -> *) a.
Monad m =>
Parser a -> SourceT m ByteString -> SourceT m a
transformWithAtto (Parser a -> SourceT m ByteString -> SourceT m a)
-> Parser a -> SourceT m ByteString -> SourceT m a
forall a b. (a -> b) -> a -> b
$ do
Int
len <- Parser Int
forall a. Integral a => Parser a
A8.decimal
Char
_ <- Char -> Parser Char
A8.char Char
':'
ByteString
bs <- Int -> Parser ByteString
A.take Int
len
Char
_ <- Char -> Parser Char
A8.char Char
','
(String -> Parser a)
-> (a -> Parser a) -> Either String a -> Parser a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either String a
f (ByteString -> ByteString
LBS.fromStrict ByteString
bs))