{-# LANGUAGE BangPatterns, FlexibleContexts, ScopedTypeVariables #-}
module Text.ProtocolBuffers.TextMessage (
-- * User API functions
-- ** Main encoding and decoding operations
        messagePutText,
        messageGetText,
-- * Internal API functions
        TextMsg(..),
        TextType(..),
        tellShow,
        tellSubMessage,
        getRead,
        getSubMessage,
    ) where

import Control.Monad.Identity (Identity)
import Control.Monad (void)
import Control.Monad.Writer (Writer, execWriter, tell, censor)
import Data.Char
import Data.Foldable (toList)
import Data.Int
import Data.List (intercalate)
import Data.Sequence (singleton)
import Data.Traversable
import Data.Word
import Text.Parsec
import Text.Printf
import Text.ProtocolBuffers.Basic
import Text.Read

import qualified Data.ByteString.Lazy.Char8 as C8
import qualified Data.ByteString.Lazy.UTF8 as U8
import qualified Text.Parsec.Token as T

type Log = Seq (Int, String)
type Output = Writer Log ()

-- | Printable and readable messages
class TextMsg a where
    textPut :: a -> Output
    textGet :: Stream s Identity Char => Parsec s () a

-- | Printable and readable field types
class TextType a where
    tellT :: String -> a -> Output
    getT :: Stream s Identity Char => String -> Parsec s () a

tells :: String -> Output
tells :: String -> Output
tells String
s = Seq (Int, String) -> Output
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Seq (Int, String) -> Output) -> Seq (Int, String) -> Output
forall a b. (a -> b) -> a -> b
$ (Int, String) -> Seq (Int, String)
forall a. a -> Seq a
singleton (Int
0, String
s)

tellShow :: Show a => String -> a -> Output
tellShow :: String -> a -> Output
tellShow String
name a
v = String -> Output
tells (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
v

tellStr :: String -> ByteString -> Output
tellStr :: String -> ByteString -> Output
tellStr String
name ByteString
s = String -> Output
tells (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ByteString -> String
dumpDecimal ByteString
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""

tellSubMessage :: TextMsg a => String -> a -> Output
tellSubMessage :: String -> a -> Output
tellSubMessage String
name a
m = do
    String -> Output
tells (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" {"
    Output -> Output
forall a.
WriterT (Seq (Int, String)) Identity a
-> WriterT (Seq (Int, String)) Identity a
indent (Output -> Output) -> Output -> Output
forall a b. (a -> b) -> a -> b
$ a -> Output
forall a. TextMsg a => a -> Output
textPut a
m
    String -> Output
tells String
"}"
    where
    indent :: WriterT (Seq (Int, String)) Identity a
-> WriterT (Seq (Int, String)) Identity a
indent = (Seq (Int, String) -> Seq (Int, String))
-> WriterT (Seq (Int, String)) Identity a
-> WriterT (Seq (Int, String)) Identity a
forall w (m :: * -> *) a. MonadWriter w m => (w -> w) -> m a -> m a
censor (((Int, String) -> (Int, String))
-> Seq (Int, String) -> Seq (Int, String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(!Int
n, String
s) -> (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, String
s)))

dumpDecimal :: ByteString -> String
dumpDecimal :: ByteString -> String
dumpDecimal = (Char -> String -> String) -> String -> ByteString -> String
forall a. (Char -> a -> a) -> a -> ByteString -> a
C8.foldr Char -> String -> String
escape []
    where
    escape :: Char -> String -> String
escape Char
'\n' String
str = String
"\\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
str
    escape Char
'\"' String
str = String
"\\\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
str
    escape Char
c String
str | Char -> Bool
isAscii Char
c Bool -> Bool -> Bool
&& Char -> Bool
isPrint Char
c = Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
str
    escape Char
c String
str = String -> Char -> String
forall r. PrintfType r => String -> r
printf String
"\\%03d" Char
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
str

instance TextType Int32 where
    tellT :: String -> Int32 -> Output
tellT = String -> Int32 -> Output
forall a. Show a => String -> a -> Output
tellShow
    getT :: String -> Parsec s () Int32
getT = Parsec s () Int32 -> String -> Parsec s () Int32
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar Parsec s () Int32
forall a s. (Integral a, Stream s Identity Char) => Parsec s () a
integer

instance TextType Int64 where
    tellT :: String -> Int64 -> Output
tellT = String -> Int64 -> Output
forall a. Show a => String -> a -> Output
tellShow
    getT :: String -> Parsec s () Int64
getT = Parsec s () Int64 -> String -> Parsec s () Int64
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar Parsec s () Int64
forall a s. (Integral a, Stream s Identity Char) => Parsec s () a
integer

instance TextType Word32 where
    tellT :: String -> Word32 -> Output
tellT = String -> Word32 -> Output
forall a. Show a => String -> a -> Output
tellShow
    getT :: String -> Parsec s () Word32
getT = Parsec s () Word32 -> String -> Parsec s () Word32
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar Parsec s () Word32
forall a s. (Integral a, Stream s Identity Char) => Parsec s () a
natural

instance TextType Word64 where
    tellT :: String -> Word64 -> Output
tellT = String -> Word64 -> Output
forall a. Show a => String -> a -> Output
tellShow
    getT :: String -> Parsec s () Word64
getT = Parsec s () Word64 -> String -> Parsec s () Word64
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar Parsec s () Word64
forall a s. (Integral a, Stream s Identity Char) => Parsec s () a
natural

instance TextType Bool where
    tellT :: String -> Bool -> Output
tellT String
name Bool
True = String -> Output
tells (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": true"
    tellT String
name Bool
False = String -> Output
tells (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": false"
    getT :: String -> Parsec s () Bool
getT String
name = do
        String
v <- Parsec s () String -> String -> Parsec s () String
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar (String -> Parsec s () String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"true" Parsec s () String -> Parsec s () String -> Parsec s () String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> Parsec s () String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"false") String
name
        Bool -> Parsec s () Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (String
v String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"true")

instance TextType Double where
    tellT :: String -> Double -> Output
tellT = String -> Double -> Output
forall a. Show a => String -> a -> Output
tellShow
    getT :: String -> Parsec s () Double
getT = Parsec s () Double -> String -> Parsec s () Double
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar Parsec s () Double
forall s. Stream s Identity Char => Parsec s () Double
float

instance TextType Float where
    tellT :: String -> Float -> Output
tellT = String -> Float -> Output
forall a. Show a => String -> a -> Output
tellShow
    getT :: String -> Parsec s () Float
getT String
name = Double -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac (Double -> Float)
-> ParsecT s () Identity Double -> Parsec s () Float
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity Double
-> String -> ParsecT s () Identity Double
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar ParsecT s () Identity Double
forall s. Stream s Identity Char => Parsec s () Double
float String
name

instance TextType Utf8 where
    tellT :: String -> Utf8 -> Output
tellT String
name (Utf8 ByteString
s) = String -> ByteString -> Output
tellStr String
name ByteString
s
    getT :: String -> Parsec s () Utf8
getT String
name = String -> Utf8
uFromString (String -> Utf8)
-> ParsecT s () Identity String -> Parsec s () Utf8
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity String
-> String -> ParsecT s () Identity String
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar ParsecT s () Identity String
forall s. Stream s Identity Char => Parsec s () String
stringLiteral String
name

instance TextType ByteString where
    tellT :: String -> ByteString -> Output
tellT = String -> ByteString -> Output
tellStr
    getT :: String -> Parsec s () ByteString
getT String
name = String -> ByteString
U8.fromString (String -> ByteString)
-> ParsecT s () Identity String -> Parsec s () ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity String
-> String -> ParsecT s () Identity String
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar ParsecT s () Identity String
forall s. Stream s Identity Char => Parsec s () String
stringLiteral String
name

instance TextType a => TextType (Maybe a) where
    tellT :: String -> Maybe a -> Output
tellT String
_ Maybe a
Nothing = () -> Output
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    tellT String
name (Just a
v) = String -> a -> Output
forall a. TextType a => String -> a -> Output
tellT String
name a
v
    getT :: String -> Parsec s () (Maybe a)
getT String
name = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> ParsecT s () Identity a -> Parsec s () (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ParsecT s () Identity a
forall a s.
(TextType a, Stream s Identity Char) =>
String -> Parsec s () a
getT String
name

instance TextType a => TextType (Seq a) where
    tellT :: String -> Seq a -> Output
tellT String
name Seq a
xs = WriterT (Seq (Int, String)) Identity (Seq ()) -> Output
forall (f :: * -> *) a. Functor f => f a -> f ()
void (WriterT (Seq (Int, String)) Identity (Seq ()) -> Output)
-> WriterT (Seq (Int, String)) Identity (Seq ()) -> Output
forall a b. (a -> b) -> a -> b
$ Seq a
-> (a -> Output) -> WriterT (Seq (Int, String)) Identity (Seq ())
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM Seq a
xs ((a -> Output) -> WriterT (Seq (Int, String)) Identity (Seq ()))
-> (a -> Output) -> WriterT (Seq (Int, String)) Identity (Seq ())
forall a b. (a -> b) -> a -> b
$ String -> a -> Output
forall a. TextType a => String -> a -> Output
tellT String
name
    getT :: String -> Parsec s () (Seq a)
getT = String -> String -> Parsec s () (Seq a)
forall a. HasCallStack => String -> a
error String
"should not take sequence directly"

-- | This writes message as text-format protobuf to 'String'
messagePutText :: TextMsg a => a -> String
messagePutText :: a -> String
messagePutText = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ([String] -> String) -> (a -> [String]) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq String -> [String]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Seq String -> [String]) -> (a -> Seq String) -> a -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, String) -> String) -> Seq (Int, String) -> Seq String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, String) -> String
setIndent (Seq (Int, String) -> Seq String)
-> (a -> Seq (Int, String)) -> a -> Seq String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Output -> Seq (Int, String)
forall w a. Writer w a -> w
execWriter (Output -> Seq (Int, String))
-> (a -> Output) -> a -> Seq (Int, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Output
forall a. TextMsg a => a -> Output
textPut
    where
    setIndent :: (Int, String) -> String
setIndent (Int
n, String
s) = Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2) Char
' ' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s

lexer :: Stream s Identity Char => T.GenTokenParser s () Identity
lexer :: GenTokenParser s () Identity
lexer = GenLanguageDef s () Identity -> GenTokenParser s () Identity
forall s (m :: * -> *) u.
Stream s m Char =>
GenLanguageDef s u m -> GenTokenParser s u m
T.makeTokenParser LanguageDef :: forall s u (m :: * -> *).
String
-> String
-> String
-> Bool
-> ParsecT s u m Char
-> ParsecT s u m Char
-> ParsecT s u m Char
-> ParsecT s u m Char
-> [String]
-> [String]
-> Bool
-> GenLanguageDef s u m
T.LanguageDef {
            identStart :: ParsecT s () Identity Char
T.identStart     = ParsecT s () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
letter ParsecT s () Identity Char
-> ParsecT s () Identity Char -> ParsecT s () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'_'
          , identLetter :: ParsecT s () Identity Char
T.identLetter    = ParsecT s () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum ParsecT s () Identity Char
-> ParsecT s () Identity Char -> ParsecT s () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'_'
          , opStart :: ParsecT s () Identity Char
T.opStart        = String -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
":!#$%&*+./<=>?@\\^|-~"
          , opLetter :: ParsecT s () Identity Char
T.opLetter       = String -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
":!#$%&*+./<=>?@\\^|-~"
          , caseSensitive :: Bool
T.caseSensitive  = Bool
True
          , commentStart :: String
T.commentStart   = String
"/*"
          , commentEnd :: String
T.commentEnd     = String
"*/"
          , commentLine :: String
T.commentLine    = String
"//"
          , nestedComments :: Bool
T.nestedComments = Bool
True
          , reservedNames :: [String]
T.reservedNames  = []
          , reservedOpNames :: [String]
T.reservedOpNames= []
    }

symbol :: Stream s Identity Char => String -> Parsec s () ()
symbol :: String -> Parsec s () ()
symbol String
sym = ParsecT s () Identity String -> Parsec s () ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT s () Identity String -> Parsec s () ())
-> ParsecT s () Identity String -> Parsec s () ()
forall a b. (a -> b) -> a -> b
$ GenTokenParser s () Identity
-> String -> ParsecT s () Identity String
forall s u (m :: * -> *).
GenTokenParser s u m -> String -> ParsecT s u m String
T.symbol GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer String
sym

colon :: Stream s Identity Char => Parsec s () ()
colon :: Parsec s () ()
colon = ParsecT s () Identity String -> Parsec s () ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT s () Identity String -> Parsec s () ())
-> ParsecT s () Identity String -> Parsec s () ()
forall a b. (a -> b) -> a -> b
$ GenTokenParser s () Identity -> ParsecT s () Identity String
forall s u (m :: * -> *).
GenTokenParser s u m -> ParsecT s u m String
T.colon GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer

braces :: Stream s Identity Char => Parsec s () a -> Parsec s () a
braces :: Parsec s () a -> Parsec s () a
braces = GenTokenParser s () Identity
-> forall a. ParsecT s () Identity a -> ParsecT s () Identity a
forall s u (m :: * -> *).
GenTokenParser s u m
-> forall a. ParsecT s u m a -> ParsecT s u m a
T.braces GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer

natural :: (Integral a, Stream s Identity Char) => Parsec s () a
natural :: Parsec s () a
natural = Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> a) -> ParsecT s () Identity Integer -> Parsec s () a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenTokenParser s () Identity -> ParsecT s () Identity Integer
forall s u (m :: * -> *).
GenTokenParser s u m -> ParsecT s u m Integer
T.natural GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer

integer :: (Integral a, Stream s Identity Char) => Parsec s () a
integer :: Parsec s () a
integer = Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> a) -> ParsecT s () Identity Integer -> Parsec s () a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenTokenParser s () Identity -> ParsecT s () Identity Integer
forall s u (m :: * -> *).
GenTokenParser s u m -> ParsecT s u m Integer
T.integer GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer

float :: Stream s Identity Char => Parsec s () Double
float :: Parsec s () Double
float = (Integer -> Double)
-> (Double -> Double) -> Either Integer Double -> Double
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Integer -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Double -> Double
forall a. a -> a
id (Either Integer Double -> Double)
-> ParsecT s () Identity (Either Integer Double)
-> Parsec s () Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenTokenParser s () Identity
-> ParsecT s () Identity (Either Integer Double)
forall s u (m :: * -> *).
GenTokenParser s u m -> ParsecT s u m (Either Integer Double)
T.naturalOrFloat GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer

stringLiteral :: Stream s Identity Char => Parsec s () String
stringLiteral :: Parsec s () String
stringLiteral = GenTokenParser s () Identity -> Parsec s () String
forall s u (m :: * -> *).
GenTokenParser s u m -> ParsecT s u m String
T.stringLiteral GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer

getRead :: forall a s . (Read a, Stream s Identity Char) => String -> Parsec s () a
getRead :: String -> Parsec s () a
getRead String
name = Parsec s () a -> Parsec s () a
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parsec s () a -> Parsec s () a) -> Parsec s () a -> Parsec s () a
forall a b. (a -> b) -> a -> b
$ do
    String
v <- Parsec s () String -> String -> Parsec s () String
forall s a.
Stream s Identity Char =>
Parsec s () a -> String -> Parsec s () a
getScalar (GenTokenParser s () Identity -> Parsec s () String
forall s u (m :: * -> *).
GenTokenParser s u m -> ParsecT s u m String
T.identifier GenTokenParser s () Identity
forall s. Stream s Identity Char => GenTokenParser s () Identity
lexer) String
name
    case String -> Maybe a
forall a. Read a => String -> Maybe a
readMaybe String
v of
        Just a
r -> a -> Parsec s () a
forall (m :: * -> *) a. Monad m => a -> m a
return a
r
        Maybe a
Nothing -> String -> Parsec s () a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parsec s () a) -> String -> Parsec s () a
forall a b. (a -> b) -> a -> b
$ String
"can't parse " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
v

getScalar :: Stream s Identity Char => Parsec s () a -> String -> Parsec s () a
getScalar :: Parsec s () a -> String -> Parsec s () a
getScalar Parsec s () a
parser String
name = String -> Parsec s () ()
forall s. Stream s Identity Char => String -> Parsec s () ()
symbol String
name Parsec s () () -> Parsec s () () -> Parsec s () ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parsec s () ()
forall s. Stream s Identity Char => Parsec s () ()
colon Parsec s () () -> Parsec s () a -> Parsec s () a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parsec s () a
parser

getSubMessage :: (Stream s Identity Char, TextMsg a) => String -> Parsec s () a
getSubMessage :: String -> Parsec s () a
getSubMessage String
name = String -> Parsec s () ()
forall s. Stream s Identity Char => String -> Parsec s () ()
symbol String
name Parsec s () () -> Parsec s () a -> Parsec s () a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parsec s () a -> Parsec s () a
forall s a.
Stream s Identity Char =>
Parsec s () a -> Parsec s () a
braces Parsec s () a
forall a s. (TextMsg a, Stream s Identity Char) => Parsec s () a
textGet

-- | This reads message as text-format protobuf from any Parsec-compatible source.
-- Input must be completely consumed.
messageGetText :: (TextMsg a, Stream s Identity Char) => s -> Either String a
messageGetText :: s -> Either String a
messageGetText s
s = case Parsec s () a -> String -> s -> Either ParseError a
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (Parsec s () a
forall a s. (TextMsg a, Stream s Identity Char) => Parsec s () a
textGet Parsec s () a -> ParsecT s () Identity () -> Parsec s () a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT s () Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof) String
"<protobuf>" s
s of
    Left ParseError
e -> String -> Either String a
forall a b. a -> Either a b
Left (ParseError -> String
forall a. Show a => a -> String
show ParseError
e)
    Right a
m -> a -> Either String a
forall a b. b -> Either a b
Right a
m