{-# 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.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 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 (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 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 :: forall a. SourceT IO a -> SourceT IO a
sourceToSourceIO = forall a. a -> a
id
instance SourceToSourceIO m => ToSourceIO chunk (SourceT m chunk) where
toSourceIO :: SourceT m chunk -> SourceIO chunk
toSourceIO = 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) = forall (m :: * -> *) a. StepT m a -> SourceT m a
fromStepT (forall (m :: * -> *) a. a -> StepT m a -> StepT m a
Yield a
x (forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall (m :: * -> *) a. a -> StepT m a -> StepT m a
Yield forall (m :: * -> *) a. StepT m a
Stop [a]
xs))
instance ToSourceIO a [a] where
toSourceIO :: [a] -> SourceIO a
toSourceIO = 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 = forall (m :: * -> *) a. MonadIO m => SourceIO a -> SourceT m a
sourceFromSourceIO
sourceFromSourceIO :: forall m a. MonadIO m => SourceT IO a -> SourceT m a
sourceFromSourceIO :: forall (m :: * -> *) a. MonadIO m => SourceIO a -> SourceT m a
sourceFromSourceIO SourceT IO a
src =
forall (m :: * -> *) a.
(forall b. (StepT m a -> m b) -> m b) -> SourceT m a
SourceT forall a b. (a -> b) -> a -> b
$ \StepT m a -> m b
k ->
StepT m a -> m b
k forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. m (StepT m a) -> StepT m a
Effect forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
SourceT m a -> forall b. (StepT m a -> m b) -> m b
unSourceT SourceT IO a
src (forall (m :: * -> *) a. Monad m => a -> m a
return 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 = forall (m :: * -> *) a. StepT m a
Stop
go (Error String
err) = forall (m :: * -> *) a. String -> StepT m a
Error String
err
go (Skip StepT IO a
s) = 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) = forall (m :: * -> *) a. m (StepT m a) -> StepT m a
Effect (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (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) = 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 :: forall (m :: * -> *) a.
Monad m =>
Proxy NoFraming
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
framingRender Proxy NoFraming
_ = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
instance FramingUnrender NoFraming where
framingUnrender :: forall (m :: * -> *) a.
Monad m =>
Proxy NoFraming
-> (ByteString -> Either String a)
-> SourceT m ByteString
-> SourceT m a
framingUnrender Proxy NoFraming
_ ByteString -> Either String a
f = forall (m :: * -> *) a b.
(StepT m a -> StepT m b) -> SourceT m a -> SourceT m b
mapStepT forall {m :: * -> *}. Functor m => StepT m ByteString -> StepT m a
go
where
go :: StepT m ByteString -> StepT m a
go StepT m ByteString
Stop = forall (m :: * -> *) a. StepT m a
Stop
go (Error String
err) = forall (m :: * -> *) a. String -> StepT m a
Error String
err
go (Skip StepT m ByteString
s) = 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) = forall (m :: * -> *) a. m (StepT m a) -> StepT m a
Effect (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 -> 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 -> forall (m :: * -> *) a. String -> StepT m a
Error String
err
data NewlineFraming
instance FramingRender NewlineFraming where
framingRender :: forall (m :: * -> *) a.
Monad m =>
Proxy NewlineFraming
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
framingRender Proxy NewlineFraming
_ a -> ByteString
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a
x -> a -> ByteString
f a
x forall a. Semigroup a => a -> a -> a
<> ByteString
"\n")
instance FramingUnrender NewlineFraming where
framingUnrender :: forall (m :: * -> *) a.
Monad m =>
Proxy NewlineFraming
-> (ByteString -> Either String a)
-> SourceT m ByteString
-> SourceT m a
framingUnrender Proxy NewlineFraming
_ ByteString -> Either String a
f = forall (m :: * -> *) a.
Monad m =>
Parser a -> SourceT m ByteString -> SourceT m a
transformWithAtto forall a b. (a -> b) -> a -> b
$ do
ByteString
bs <- (Word8 -> Bool) -> Parser ByteString
A.takeWhile (forall a. Eq a => a -> a -> Bool
/= Word8
10)
() forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Word8 -> Parser Word8
A.word8 Word8
10 forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall t. Chunk t => Parser t ()
A.endOfInput
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (m :: * -> *) a. MonadFail m => String -> m a
fail 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 :: forall (m :: * -> *) a.
Monad m =>
Proxy NetstringFraming
-> (a -> ByteString) -> SourceT m a -> SourceT m ByteString
framingRender Proxy NetstringFraming
_ a -> ByteString
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a -> b) -> a -> b
$ \a
x ->
let bs :: ByteString
bs = a -> ByteString
f a
x
in String -> ByteString
LBS8.pack (forall a. Show a => a -> String
show (ByteString -> Int64
LBS8.length ByteString
bs)) forall a. Semigroup a => a -> a -> a
<> ByteString
":" forall a. Semigroup a => a -> a -> a
<> ByteString
bs forall a. Semigroup a => a -> a -> a
<> ByteString
","
instance FramingUnrender NetstringFraming where
framingUnrender :: forall (m :: * -> *) a.
Monad m =>
Proxy NetstringFraming
-> (ByteString -> Either String a)
-> SourceT m ByteString
-> SourceT m a
framingUnrender Proxy NetstringFraming
_ ByteString -> Either String a
f = forall (m :: * -> *) a.
Monad m =>
Parser a -> SourceT m ByteString -> SourceT m a
transformWithAtto forall a b. (a -> b) -> a -> b
$ do
Int
len <- 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
','
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either String a
f (ByteString -> ByteString
LBS.fromStrict ByteString
bs))