Z-Data 0.8.0.0 → 0.8.1.0
raw patch · 6 files changed
+62/−60 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Z.Data.JSON: parseValueChunks :: Monad m => ParseChunks m Bytes ParseError Value
- Z.Data.JSON.Base: parseValueChunks :: Monad m => ParseChunks m Bytes ParseError Value
- Z.Data.JSON.Value: parseValueChunks :: Monad m => ParseChunks m Bytes ParseError Value
- Z.Data.Parser.Base: instance GHC.Base.Functor Z.Data.Parser.Base.Result
- Z.Data.Parser.Base: instance GHC.Show.Show a => GHC.Show.Show (Z.Data.Parser.Base.Result a)
+ Z.Data.JSON: decodeChunk :: JSON a => Bytes -> Result DecodeError a
+ Z.Data.JSON.Base: decodeChunk :: JSON a => Bytes -> Result DecodeError a
+ Z.Data.Parser.Base: instance (GHC.Show.Show e, GHC.Show.Show a) => GHC.Show.Show (Z.Data.Parser.Base.Result e a)
+ Z.Data.Parser.Base: instance GHC.Base.Functor (Z.Data.Parser.Base.Result e)
- Z.Data.JSON: decodeChunks :: (JSON a, Monad m) => ParseChunks m Bytes DecodeError a
+ Z.Data.JSON: decodeChunks :: (JSON a, Monad m) => ParseChunks m DecodeError a
- Z.Data.JSON: type ParseChunks m chunk err x = m chunk -> chunk -> m (chunk, Either err x)
+ Z.Data.JSON: type ParseChunks m err x = m Bytes -> Bytes -> m (Bytes, Either err x)
- Z.Data.JSON.Base: decodeChunks :: (JSON a, Monad m) => ParseChunks m Bytes DecodeError a
+ Z.Data.JSON.Base: decodeChunks :: (JSON a, Monad m) => ParseChunks m DecodeError a
- Z.Data.JSON.Base: type ParseChunks m chunk err x = m chunk -> chunk -> m (chunk, Either err x)
+ Z.Data.JSON.Base: type ParseChunks m err x = m Bytes -> Bytes -> m (Bytes, Either err x)
- Z.Data.Parser: Failure :: ParseError -> !Bytes -> Result a
+ Z.Data.Parser: Failure :: e -> !Bytes -> Result e r
- Z.Data.Parser: Partial :: ParseStep a -> Result a
+ Z.Data.Parser: Partial :: ParseStep e r -> Result e r
- Z.Data.Parser: Success :: a -> !Bytes -> Result a
+ Z.Data.Parser: Success :: r -> !Bytes -> Result e r
- Z.Data.Parser: data Result a
+ Z.Data.Parser: data Result e r
- Z.Data.Parser: finishParsing :: Result a -> (Bytes, Either ParseError a)
+ Z.Data.Parser: finishParsing :: Result ParseError a -> (Bytes, Either ParseError a)
- Z.Data.Parser: parseChunk :: Parser a -> Bytes -> Result a
+ Z.Data.Parser: parseChunk :: Parser a -> Bytes -> Result ParseError a
- Z.Data.Parser: parseChunks :: Monad m => Parser a -> ParseChunks m Bytes ParseError a
+ Z.Data.Parser: parseChunks :: Monad m => (Bytes -> Result e a) -> ParseChunks m e a
- Z.Data.Parser: runAndKeepTrack :: Parser a -> Parser (Result a, [Bytes])
+ Z.Data.Parser: runAndKeepTrack :: Parser a -> Parser (Result ParseError a, [Bytes])
- Z.Data.Parser: type ParseChunks m chunk err x = m chunk -> chunk -> m (chunk, Either err x)
+ Z.Data.Parser: type ParseChunks m err x = m Bytes -> Bytes -> m (Bytes, Either err x)
- Z.Data.Parser.Base: Failure :: ParseError -> !Bytes -> Result a
+ Z.Data.Parser.Base: Failure :: e -> !Bytes -> Result e r
- Z.Data.Parser.Base: Parser :: (forall r. (ParseError -> ParseStep r) -> (State# ParserState -> a -> ParseStep r) -> State# ParserState -> ParseStep r) -> Parser a
+ Z.Data.Parser.Base: Parser :: (forall r. (ParseError -> ParseStep ParseError r) -> (State# ParserState -> a -> ParseStep ParseError r) -> State# ParserState -> ParseStep ParseError r) -> Parser a
- Z.Data.Parser.Base: Partial :: ParseStep a -> Result a
+ Z.Data.Parser.Base: Partial :: ParseStep e r -> Result e r
- Z.Data.Parser.Base: Success :: a -> !Bytes -> Result a
+ Z.Data.Parser.Base: Success :: r -> !Bytes -> Result e r
- Z.Data.Parser.Base: [runParser] :: Parser a -> forall r. (ParseError -> ParseStep r) -> (State# ParserState -> a -> ParseStep r) -> State# ParserState -> ParseStep r
+ Z.Data.Parser.Base: [runParser] :: Parser a -> forall r. (ParseError -> ParseStep ParseError r) -> (State# ParserState -> a -> ParseStep ParseError r) -> State# ParserState -> ParseStep ParseError r
- Z.Data.Parser.Base: data Result a
+ Z.Data.Parser.Base: data Result e r
- Z.Data.Parser.Base: finishParsing :: Result a -> (Bytes, Either ParseError a)
+ Z.Data.Parser.Base: finishParsing :: Result ParseError a -> (Bytes, Either ParseError a)
- Z.Data.Parser.Base: parseChunk :: Parser a -> Bytes -> Result a
+ Z.Data.Parser.Base: parseChunk :: Parser a -> Bytes -> Result ParseError a
- Z.Data.Parser.Base: parseChunks :: Monad m => Parser a -> ParseChunks m Bytes ParseError a
+ Z.Data.Parser.Base: parseChunks :: Monad m => (Bytes -> Result e a) -> ParseChunks m e a
- Z.Data.Parser.Base: runAndKeepTrack :: Parser a -> Parser (Result a, [Bytes])
+ Z.Data.Parser.Base: runAndKeepTrack :: Parser a -> Parser (Result ParseError a, [Bytes])
- Z.Data.Parser.Base: type ParseChunks m chunk err x = m chunk -> chunk -> m (chunk, Either err x)
+ Z.Data.Parser.Base: type ParseChunks m err x = m Bytes -> Bytes -> m (Bytes, Either err x)
- Z.Data.Parser.Base: type ParseStep r = Bytes -> Result r
+ Z.Data.Parser.Base: type ParseStep e r = Bytes -> Result e r
Files
- ChangeLog.md +5/−0
- Z-Data.cabal +1/−1
- Z/Data/JSON.hs +2/−2
- Z/Data/JSON/Base.hs +18/−11
- Z/Data/JSON/Value.hs +0/−6
- Z/Data/Parser/Base.hs +36/−40
ChangeLog.md view
@@ -1,5 +1,10 @@ # Revision history for Z-Data +## 0.8.1.0 -- 2021-04-23++* Change `ParseChunks` and `parseChunks` to based on `parseChunk`.+* Remove `parseValueChunks`, add `decodeChunk` to `Z.Data.JSON`.+ ## 0.8.0.0 -- 2021-04-20 * Change `Bytes` 's `Hashable` instance to use FNV-1a (proposed by @zypeh).
Z-Data.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: Z-Data-version: 0.8.0.0+version: 0.8.1.0 synopsis: Array, vector and text description: This package provides array, slice and text operations license: BSD-3-Clause
Z/Data/JSON.hs view
@@ -32,11 +32,11 @@ -- * Encode & Decode , DecodeError , decode, decode', decodeText, decodeText'- , ParseChunks, decodeChunks+ , ParseChunks, decodeChunk, decodeChunks , encode, encodeChunks, encodeText , prettyJSON, prettyValue -- * parse into JSON Value- , parseValue, parseValue', parseValueChunks+ , parseValue, parseValue' -- * Generic functions , gToValue, gFromValue, gEncodeJSON -- * Convert 'Value' to Haskell data
Z/Data/JSON/Base.hs view
@@ -18,11 +18,11 @@ , -- * Encode & Decode DecodeError , decode, decode', decodeText, decodeText'- , P.ParseChunks, decodeChunks+ , P.ParseChunks, decodeChunk, decodeChunks , encode, encodeChunks, encodeText , prettyJSON, JB.prettyValue -- * parse into JSON Value- , JV.parseValue, JV.parseValue', JV.parseValueChunks+ , JV.parseValue, JV.parseValue' -- * Generic functions , gToValue, gFromValue, gEncodeJSON -- * Convert 'Value' to Haskell data@@ -146,17 +146,24 @@ Left cErr -> (bs', Left (Right cErr)) Right r -> (bs', Right r) +-- | Decode a JSON doc chunk.+decodeChunk :: JSON a => V.Bytes -> P.Result DecodeError a+{-# INLINE decodeChunk #-}+decodeChunk bs = loop (P.parseChunk JV.value bs)+ where+ loop r = do+ case r of+ P.Success v rest ->+ case convertValue v of+ Left cErr -> P.Failure (Right cErr) rest+ Right r' -> P.Success r' rest+ P.Failure e rest -> P.Failure (Left e) rest+ P.Partial f' -> P.Partial (loop . f')+ -- | Decode JSON doc chunks, return trailing bytes.-decodeChunks :: (JSON a, Monad m) => P.ParseChunks m V.Bytes DecodeError a+decodeChunks :: (JSON a, Monad m) => P.ParseChunks m DecodeError a {-# INLINE decodeChunks #-}-decodeChunks mb bs = do- mr <- P.parseChunks JV.value mb bs- case mr of- (bs', Left pErr) -> pure (bs', Left (Left pErr))- (bs', Right v) ->- case convertValue v of- Left cErr -> pure (bs', Left (Right cErr))- Right r -> pure (bs', Right r)+decodeChunks = P.parseChunks decodeChunk -- | Directly encode data to JSON bytes. encode :: JSON a => a -> V.Bytes
Z/Data/JSON/Value.hs view
@@ -27,7 +27,6 @@ -- * parse into JSON Value , parseValue , parseValue'- , parseValueChunks -- * Value Parsers , value , object@@ -149,11 +148,6 @@ parseValue' :: V.Bytes -> Either P.ParseError Value {-# INLINE parseValue' #-} parseValue' = P.parse' (value <* skipSpaces <* P.endOfInput)---- | Increamental parse 'Value' without consuming trailing bytes.-parseValueChunks :: Monad m => P.ParseChunks m V.Bytes P.ParseError Value-{-# INLINE parseValueChunks #-}-parseValueChunks = P.parseChunks value --------------------------------------------------------------------------------
Z/Data/Parser/Base.hs view
@@ -64,23 +64,23 @@ -- -- * Partial: that need for more input data, supply empty bytes to indicate 'endOfInput' ---data Result a- = Success a !V.Bytes- | Failure ParseError !V.Bytes- | Partial (ParseStep a)+data Result e r+ = Success r !V.Bytes+ | Failure e !V.Bytes+ | Partial (ParseStep e r) -- | A parse step consumes 'V.Bytes' and produce 'Result'.-type ParseStep r = V.Bytes -> Result r+type ParseStep e r = V.Bytes -> Result e r -- | Type alias for error message type ParseError = [T.Text] -instance Functor Result where+instance Functor (Result e) where fmap f (Success a s) = Success (f a) s fmap f (Partial k) = Partial (fmap f . k) fmap _ (Failure e v) = Failure e v -instance Show a => Show (Result a) where+instance (Show e, Show a) => Show (Result e a) where show (Success a _) = "Success " ++ show a show (Partial _) = "Partial _" show (Failure errs _) = "Failure: " ++ show errs@@ -100,9 +100,9 @@ -- ... k s ... (if we get something useful for next parser) -- @ newtype Parser a = Parser {- runParser :: forall r . (ParseError -> ParseStep r)- -> (State# ParserState -> a -> ParseStep r)- -> State# ParserState -> ParseStep r+ runParser :: forall r . (ParseError -> ParseStep ParseError r)+ -> (State# ParserState -> a -> ParseStep ParseError r)+ -> State# ParserState -> ParseStep ParseError r } -- | State token tag used in `Parser`@@ -195,38 +195,32 @@ unsafeCoerce# (p Failure (\ _ r -> Success r) (unsafeCoerce# s) inp))) -- | Parse an input chunk-parseChunk :: Parser a -> V.Bytes -> Result a+parseChunk :: Parser a -> V.Bytes -> Result ParseError a {-# INLINE parseChunk #-} parseChunk (Parser p) = runRW# (\ s -> unsafeCoerce# (p Failure (\ _ r -> Success r) (unsafeCoerce# s))) -- | Finish parsing and fetch result, feed empty bytes if it's 'Partial' result.-finishParsing :: Result a -> (V.Bytes, Either ParseError a)+finishParsing :: Result ParseError a -> (V.Bytes, Either ParseError a) {-# INLINABLE finishParsing #-} finishParsing r = case r of Success a rest -> (rest, Right a) Failure errs rest -> (rest, Left errs) Partial f -> finishParsing (f V.empty) --- | Type alias for a streaming parser, draw chunk from Monad m (with a initial chunk), return result in @Either err x@.-type ParseChunks m chunk err x = m chunk -> chunk -> m (chunk, Either err x)+-- | Type alias for a streaming parser, draw chunk from Monad m with a initial chunk,+-- return result in @Either err x@.+type ParseChunks m err x = m V.Bytes -> V.Bytes -> m (V.Bytes, Either err x) --- | Run a parser with an initial input string, and a monadic action+-- | Run a chunk parser with an initial input string, and a monadic action -- that can supply more input if needed. ----- Note, once the monadic action return empty bytes, parsers will stop drawing--- more bytes (take it as 'endOfInput').-parseChunks :: Monad m => Parser a -> ParseChunks m V.Bytes ParseError a+parseChunks :: Monad m => (V.Bytes -> Result e a) -> ParseChunks m e a {-# INLINABLE parseChunks #-}-parseChunks (Parser p) m0 inp = go m0 (runRW# (\ s ->- unsafeCoerce# (p Failure (\ _ r -> Success r) (unsafeCoerce# s) inp)))+parseChunks pc m0 inp = go m0 (pc inp) where go m r = case r of- Partial f -> do- inp' <- m- if V.null inp'- then go (pure V.empty) (f V.empty)- else go m (f inp')+ Partial f -> go m . f =<< m Success a rest -> pure (rest, Right a) Failure errs rest -> pure (rest, Left errs) @@ -239,7 +233,7 @@ -- Once it's finished, return the final result (always 'Success' or 'Failure') and -- all consumed chunks. ---runAndKeepTrack :: Parser a -> Parser (Result a, [V.Bytes])+runAndKeepTrack :: Parser a -> Parser (Result ParseError a, [V.Bytes]) {-# INLINE runAndKeepTrack #-} runAndKeepTrack (Parser pa) = Parser $ \ _ k0 st0 inp -> let go !acc r k (st :: State# ParserState) = case r of@@ -277,9 +271,9 @@ else Partial (ensureNPartial l inp kf k s) where {-# INLINABLE ensureNPartial #-}- ensureNPartial :: forall r. Int -> V.PrimVector Word8 -> (ParseError -> ParseStep r)- -> (State# ParserState -> () -> ParseStep r)- -> State# ParserState -> ParseStep r+ ensureNPartial :: forall r. Int -> V.PrimVector Word8 -> (ParseError -> ParseStep ParseError r)+ -> (State# ParserState -> () -> ParseStep ParseError r)+ -> State# ParserState -> ParseStep ParseError r ensureNPartial l0 inp0 kf k s0 = let go acc !l s = \ inp -> do let l' = V.length inp@@ -432,8 +426,8 @@ where -- we want to inline consume if possible {-# INLINABLE scanChunksPartial #-}- scanChunksPartial :: forall r. s -> (State# ParserState -> (V.PrimVector Word8, s) -> ParseStep r)- -> State# ParserState -> V.PrimVector Word8 -> ParseStep r+ scanChunksPartial :: forall r. s -> (State# ParserState -> (V.PrimVector Word8, s) -> ParseStep ParseError r)+ -> State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r scanChunksPartial s0' k st0 inp0 = let go s acc st = \ inp -> if V.null inp@@ -621,8 +615,9 @@ then k s () $! V.unsafeDrop n' inp else Partial (skipPartial (n'-l) kf k s)) -skipPartial :: Int -> (ParseError -> ParseStep r) -> (State# ParserState -> () -> ParseStep r)- -> State# ParserState -> ParseStep r+skipPartial :: Int -> (ParseError -> ParseStep ParseError r)+ -> (State# ParserState -> () -> ParseStep ParseError r)+ -> State# ParserState -> ParseStep ParseError r {-# INLINABLE skipPartial #-} skipPartial n kf k s0 = let go !n' s = \ inp ->@@ -660,7 +655,8 @@ where -- we want to inline p if possible {-# INLINABLE skipWhilePartial #-}- skipWhilePartial :: forall r. (State# ParserState -> () -> ParseStep r) -> State# ParserState -> ParseStep r+ skipWhilePartial :: forall r. (State# ParserState -> () -> ParseStep ParseError r)+ -> State# ParserState -> ParseStep ParseError r skipWhilePartial k s0 = let go s = \ inp -> if V.null inp@@ -699,8 +695,8 @@ else k s want rest) where {-# INLINABLE takeTillPartial #-}- takeTillPartial :: forall r. (State# ParserState -> V.PrimVector Word8 -> ParseStep r)- -> State# ParserState -> V.PrimVector Word8 -> ParseStep r+ takeTillPartial :: forall r. (State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r)+ -> State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r takeTillPartial k s0 want = let go acc s = \ inp -> if V.null inp@@ -726,8 +722,8 @@ where -- we want to inline p if possible {-# INLINABLE takeWhilePartial #-}- takeWhilePartial :: forall r. (State# ParserState -> V.PrimVector Word8 -> ParseStep r)- -> State# ParserState -> V.PrimVector Word8 -> ParseStep r+ takeWhilePartial :: forall r. (State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r)+ -> State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r takeWhilePartial k s0 want = let go acc s = \ inp -> if V.null inp@@ -759,8 +755,8 @@ takeRemaining = Parser (\ _ k s inp -> Partial (takeRemainingPartial k s inp)) where {-# INLINABLE takeRemainingPartial #-}- takeRemainingPartial :: forall r. (State# ParserState -> V.PrimVector Word8 -> ParseStep r)- -> State# ParserState -> V.PrimVector Word8 -> ParseStep r+ takeRemainingPartial :: forall r. (State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r)+ -> State# ParserState -> V.PrimVector Word8 -> ParseStep ParseError r takeRemainingPartial k s0 want = let go acc s = \ inp -> if V.null inp