proto-lens 0.1.0.2 → 0.1.0.3
raw patch · 4 files changed
+93/−14 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.ProtoLens.Message: def :: Default a => a
+ Data.ProtoLens.Message: def :: a
Files
- proto-lens.cabal +1/−1
- src/Data/ProtoLens/Encoding.hs +0/−1
- src/Data/ProtoLens/TextFormat.hs +32/−6
- src/Data/ProtoLens/TextFormat/Parser.hs +60/−6
proto-lens.cabal view
@@ -1,5 +1,5 @@ name: proto-lens-version: 0.1.0.2+version: 0.1.0.3 synopsis: A lens-based implementation of protocol buffers in Haskell. description: The proto-lens library provides to protocol buffers using modern
src/Data/ProtoLens/Encoding.hs view
@@ -223,4 +223,3 @@ stringizeError :: Either UnicodeException a -> Either String a stringizeError (Left e) = Left (show e) stringizeError (Right a) = Right a-
src/Data/ProtoLens/TextFormat.hs view
@@ -20,13 +20,15 @@ import Lens.Family2 ((&),(^.),(.~), set, over) import Control.Applicative ((<$>)) import Control.Arrow (left)-import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString+import Data.Char (isPrint, isAscii, chr) import Data.Foldable (foldlM, foldl') import Data.Maybe (catMaybes) import qualified Data.Map as Map import qualified Data.Set as Set-import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text import qualified Data.Text.Lazy as Lazy+import Numeric (showOct) import Text.Parsec (parse) import Text.PrettyPrint @@ -102,11 +104,35 @@ pprintFieldValue name FloatField x = primField name x pprintFieldValue name DoubleField x = primField name x pprintFieldValue name BoolField x = text name <> colon <+> boolValue x-pprintFieldValue name StringField x = primField name x-pprintFieldValue name BytesField x = primField name x+pprintFieldValue name StringField x = pprintByteString name (Text.encodeUtf8 x)+pprintFieldValue name BytesField x = pprintByteString name x pprintFieldValue name GroupField m = text name <+> lbrace $$ nest 2 (pprintMessage m) $$ rbrace +-- | Formats a string in a way that mostly matches the C-compatible escaping+-- used by the Protocol Buffer distribution. We depart a bit by escaping all+-- non-ASCII characters, which depending on the locale, the distribution might+-- not do.+--+-- This uses three-digit octal escapes, e.g. "\011" plus \n, \r,, \t, \', \",+-- and \\ only. Note that Haskell string-literal syntax calls for "\011" to be+-- interpreted as decimal 11, rather than the decimal 9 it actually represent,+-- so you can't use Prelude.read to parse the strings created here.+pprintByteString :: String -> Data.ByteString.ByteString -> Doc+pprintByteString name x = text name <> colon <+> char '\"'+ <> text (concatMap escape $ Data.ByteString.unpack x) <> char '\"'+ where escape w8 | ch == '\n' = "\\n"+ | ch == '\r' = "\\r"+ | ch == '\t' = "\\t"+ | ch == '\"' = "\\\""+ | ch == '\'' = "\\\'"+ | ch == '\\' = "\\\\"+ | isPrint ch && isAscii ch = ch : ""+ | otherwise = "\\" ++ pad (showOct w8 "")+ where+ ch = chr $ fromIntegral w8+ pad str = replicate (3 - length str) '0' ++ str+ primField :: Show value => String -> value -> Doc primField name x = text name <> colon <+> text (show x) @@ -202,8 +228,8 @@ | x == "true" = Right True | x == "false" = Right False | otherwise = Left $ "Unrecognized bool value " ++ show x-makeValue StringField (Parser.StringValue x) = Right (Text.pack x)-makeValue BytesField (Parser.StringValue x) = Right (B.pack x)+makeValue StringField (Parser.ByteStringValue x) = Right (Text.decodeUtf8 x)+makeValue BytesField (Parser.ByteStringValue x) = Right x makeValue EnumField (Parser.IntValue x) = maybe (Left $ "Unrecognized enum value " ++ show x) Right (maybeToEnum $ fromInteger x)
src/Data/ProtoLens/TextFormat/Parser.hs view
@@ -14,13 +14,19 @@ , parser ) where -import Data.List (intercalate)+import Data.ByteString (ByteString, pack)+import Data.Char (ord) import Data.Functor.Identity (Identity)+import Data.List (intercalate)+import Data.Maybe (catMaybes) import Data.Text.Lazy (Text)-import Text.Parsec.Char (alphaNum, char, letter, oneOf)+import Data.Word (Word8)+import Numeric (readOct, readHex)+import Text.Parsec.Char+ (alphaNum, char, hexDigit, letter, octDigit, oneOf, satisfy) import Text.Parsec.Text.Lazy (Parser)-import Text.Parsec.Combinator (eof, sepBy1, many1, choice)-import Text.Parsec.Token+import Text.Parsec.Combinator (choice, eof, many1, optionMaybe, sepBy1)+import Text.Parsec.Token hiding (octal) import Control.Applicative ((<*), (<|>), (*>), many) import Control.Monad (liftM, liftM2, mzero) @@ -60,7 +66,7 @@ data Value = IntValue Integer -- ^ An integer | DoubleValue Double -- ^ Any floating point number- | StringValue String -- ^ A string literal+ | ByteStringValue ByteString -- ^ A string or bytes literal | MessageValue Message -- ^ A sub message | EnumValue String -- ^ Any undelimited string (including false & true) deriving (Show,Ord,Eq)@@ -91,7 +97,8 @@ negative <- (symbol ptp "-" >> return True) <|> return False value <- naturalOrFloat ptp return $ makeNumberValue negative value- parseString = liftM (StringValue . concat) . many1 $ stringLiteral ptp+ parseString = liftM (ByteStringValue . mconcat)+ $ many1 $ lexeme ptp $ protoStringLiteral parseEnumValue = liftM EnumValue (identifier ptp) parseMessageValue = liftM MessageValue (braces ptp parseMessage <|> angles ptp parseMessage)@@ -101,3 +108,50 @@ makeNumberValue False (Left intValue) = IntValue intValue makeNumberValue True (Right doubleValue) = DoubleValue (negate doubleValue) makeNumberValue False (Right doubleValue) = DoubleValue doubleValue++-- | Reads a literal string the way the Protocol Buffer distribution's+-- tokenizer.cc does. This differs from Haskell string literals in treating,+-- e.g. "\11" as octal instead of decimal, so reading as 9 instead of 11. Also,+-- like tokenizer.cc we assume octal and hex escapes can have at most three and+-- two digits, respectively.+--+-- TODO: implement reading of Unicode escapes.+protoStringLiteral :: Parser ByteString+protoStringLiteral = do+ initialQuoteChar <- char '\'' <|> char '\"'+ word8s <- many stringChar+ _ <- char initialQuoteChar+ return $ pack word8s+ where+ stringChar :: Parser Word8+ stringChar = nonEscape <|> stringEscape+ nonEscape = fmap (fromIntegral . ord)+ $ satisfy (\c -> c `notElem` "\\\'\"" && ord c < 256)+ stringEscape = char '\\' >> (octal <|> hex <|> unicode <|> simple)+ octal = do d0 <- octDigit+ d1 <- optionMaybe octDigit+ d2 <- optionMaybe octDigit+ readMaybeDigits readOct [Just d0, d1, d2]+ readMaybeDigits :: ReadS Word8 -> [Maybe Char] -> Parser Word8+ readMaybeDigits reader+ = return . (\str -> let [(v, "")] = reader str in v) . catMaybes+ hex = do _ <- oneOf "xX"+ d0 <- hexDigit+ d1 <- optionMaybe hexDigit+ readMaybeDigits readHex [Just d0, d1]+ unicode = oneOf "uU" >> fail "Unicode in string literals not yet supported"+ simple = choice $ map charRet [ ('a', '\a')+ , ('b', '\b')+ , ('f', '\f')+ , ('n', '\n')+ , ('r', '\r')+ , ('t', '\t')+ , ('v', '\v')+ , ('\\', '\\')+ , ('\'', '\'')+ , ('\"', '\"')+ ]+ where+ charRet :: (Char, Char) -> Parser Word8+ charRet (escapeCh, ch) = do _ <- char escapeCh+ return $ fromIntegral $ ord ch