hw-json 0.0.0.2 → 0.0.0.3
raw patch · 4 files changed
+190/−156 lines, 4 filesdep ~basedep ~hw-primdep ~hw-rankselectPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base, hw-prim, hw-rankselect
API changes (from Hackage documentation)
- HaskellWorks.Data.Json.Succinct.Cursor.Internal: instance HaskellWorks.Data.Bits.BitWise.TestBit w => HaskellWorks.Data.Json.Type.JsonTypeAt (HaskellWorks.Data.Json.Succinct.Cursor.Internal.JsonCursor Data.ByteString.Internal.ByteString v w)
- HaskellWorks.Data.Json.Succinct.Cursor.Internal: instance HaskellWorks.Data.Bits.BitWise.TestBit w => HaskellWorks.Data.Json.Value.JsonValueAt Data.ByteString.Internal.ByteString Data.ByteString.Internal.ByteString (HaskellWorks.Data.Json.Succinct.Cursor.Internal.JsonCursor Data.ByteString.Internal.ByteString v w)
+ HaskellWorks.Data.Json.Succinct.Cursor.Internal: instance (HaskellWorks.Data.Succinct.BalancedParens.Internal.BalancedParens w, HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0.Rank0 w, HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank1.Rank1 w, HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Select1.Select1 v, HaskellWorks.Data.Bits.BitWise.TestBit w) => HaskellWorks.Data.Json.Type.JsonTypeAt (HaskellWorks.Data.Json.Succinct.Cursor.Internal.JsonCursor Data.ByteString.Internal.ByteString v w)
+ HaskellWorks.Data.Json.Succinct.Cursor.Internal: instance (HaskellWorks.Data.Succinct.BalancedParens.Internal.BalancedParens w, HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0.Rank0 w, HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank1.Rank1 w, HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Select1.Select1 v, HaskellWorks.Data.Bits.BitWise.TestBit w) => HaskellWorks.Data.Json.Value.JsonValueAt Data.ByteString.Internal.ByteString Data.ByteString.Internal.ByteString (HaskellWorks.Data.Json.Succinct.Cursor.Internal.JsonCursor Data.ByteString.Internal.ByteString v w)
- HaskellWorks.Data.Json.Succinct.Cursor.CursorType: jsonCursorType :: HasJsonCursorType k => k -> JsonCursorType
+ HaskellWorks.Data.Json.Succinct.Cursor.CursorType: jsonCursorType :: HasJsonCursorType k => k -> Maybe JsonCursorType
Files
- hw-json.cabal +2/−1
- src/HaskellWorks/Data/Json/Succinct/Cursor/CursorType.hs +21/−21
- src/HaskellWorks/Data/Json/Succinct/Cursor/Internal.hs +77/−50
- test/HaskellWorks/Data/Json/Succinct/CursorSpec.hs +90/−84
hw-json.cabal view
@@ -1,5 +1,5 @@ name: hw-json-version: 0.0.0.2+version: 0.0.0.3 synopsis: Conduits for tokenizing streams. description: Please see README.md homepage: http://github.com/haskell-works/hw-json#readme@@ -84,6 +84,7 @@ build-depends: base , attoparsec , bytestring+ , containers , conduit , hspec , hw-bits
src/HaskellWorks/Data/Json/Succinct/Cursor/CursorType.hs view
@@ -27,29 +27,29 @@ deriving (Eq, Show) class HasJsonCursorType k where- jsonCursorType :: k -> JsonCursorType+ jsonCursorType :: k -> Maybe JsonCursorType -jsonCursorType' :: Char -> JsonCursorType+jsonCursorType' :: Char -> Maybe JsonCursorType jsonCursorType' c = case c of- '[' -> JsonCursorArray- 't' -> JsonCursorBool- 'f' -> JsonCursorBool- '0' -> JsonCursorNumber- '1' -> JsonCursorNumber- '2' -> JsonCursorNumber- '3' -> JsonCursorNumber- '4' -> JsonCursorNumber- '5' -> JsonCursorNumber- '6' -> JsonCursorNumber- '7' -> JsonCursorNumber- '8' -> JsonCursorNumber- '9' -> JsonCursorNumber- '+' -> JsonCursorNumber- '-' -> JsonCursorNumber- 'n' -> JsonCursorNull- '{' -> JsonCursorObject- '"' -> JsonCursorString- _ -> error "Invalid JsonCursor cursorRank"+ '[' -> Just JsonCursorArray+ 't' -> Just JsonCursorBool+ 'f' -> Just JsonCursorBool+ '0' -> Just JsonCursorNumber+ '1' -> Just JsonCursorNumber+ '2' -> Just JsonCursorNumber+ '3' -> Just JsonCursorNumber+ '4' -> Just JsonCursorNumber+ '5' -> Just JsonCursorNumber+ '6' -> Just JsonCursorNumber+ '7' -> Just JsonCursorNumber+ '8' -> Just JsonCursorNumber+ '9' -> Just JsonCursorNumber+ '+' -> Just JsonCursorNumber+ '-' -> Just JsonCursorNumber+ 'n' -> Just JsonCursorNull+ '{' -> Just JsonCursorObject+ '"' -> Just JsonCursorString+ _ -> Nothing jsonCursorPos :: (Rank1 w, Select1 v, VectorLike s) => JsonCursor s v w -> Position jsonCursorPos k = toPosition (select1 ik (rank1 bpk (cursorRank k)) - 1)
src/HaskellWorks/Data/Json/Succinct/Cursor/Internal.hs view
@@ -2,16 +2,19 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} module HaskellWorks.Data.Json.Succinct.Cursor.Internal ( JsonCursor(..) ) where -import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BSC-import Data.ByteString.Internal as BSI+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import Data.ByteString.Internal as BSI+import qualified Data.List as L+import qualified Data.Map as M import Data.String-import qualified Data.Vector.Storable as DVS+import qualified Data.Vector.Storable as DVS import Data.Word import Data.Word8 import Foreign.ForeignPtr@@ -19,15 +22,17 @@ import HaskellWorks.Data.Bits.BitWise import HaskellWorks.Data.FromByteString import HaskellWorks.Data.FromForeignRegion-import HaskellWorks.Data.Json.Succinct.Cursor.BalancedParens+import HaskellWorks.Data.Json.Extract+import qualified HaskellWorks.Data.Json.Succinct.Cursor.BalancedParens as CBP import HaskellWorks.Data.Json.Succinct.Cursor.BlankedJson import HaskellWorks.Data.Json.Succinct.Cursor.InterestBits import HaskellWorks.Data.Json.Type import HaskellWorks.Data.Json.Value import HaskellWorks.Data.Positioning-import HaskellWorks.Data.Succinct.BalancedParens as BP+import qualified HaskellWorks.Data.Succinct.BalancedParens as BP import HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0 import HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank1+import HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Select1 import HaskellWorks.Data.Succinct.RankSelect.Binary.Poppy512 import HaskellWorks.Data.TreeCursor import HaskellWorks.Data.Vector.VectorLike@@ -40,67 +45,67 @@ } deriving (Eq, Show) -instance (FromBlankedJson (JsonInterestBits a), FromBlankedJson (JsonBalancedParens b))+instance (FromBlankedJson (JsonInterestBits a), FromBlankedJson (CBP.JsonBalancedParens b)) => FromByteString (JsonCursor BS.ByteString a b) where fromByteString bs = JsonCursor { cursorText = bs , interests = getJsonInterestBits (fromBlankedJson blankedJson)- , balancedParens = getJsonBalancedParens (fromBlankedJson blankedJson)+ , balancedParens = CBP.getJsonBalancedParens (fromBlankedJson blankedJson) , cursorRank = 1 } where blankedJson :: BlankedJson blankedJson = fromByteString bs -instance IsString (JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])) where- fromString :: String -> JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])+instance IsString (JsonCursor String (BitShown [Bool]) (BP.SimpleBalancedParens [Bool])) where+ fromString :: String -> JsonCursor String (BitShown [Bool]) (BP.SimpleBalancedParens [Bool]) fromString s = JsonCursor { cursorText = s , cursorRank = 1 , interests = getJsonInterestBits (fromBlankedJson blankedJson)- , balancedParens = getJsonBalancedParens (fromBlankedJson blankedJson)+ , balancedParens = CBP.getJsonBalancedParens (fromBlankedJson blankedJson) } where blankedJson :: BlankedJson blankedJson = fromByteString (BSC.pack s) -instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word8)) (SimpleBalancedParens (DVS.Vector Word8))) where+instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word8)) (BP.SimpleBalancedParens (DVS.Vector Word8))) where fromString = fromByteString . BSC.pack -instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word16)) (SimpleBalancedParens (DVS.Vector Word16))) where+instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word16)) (BP.SimpleBalancedParens (DVS.Vector Word16))) where fromString = fromByteString . BSC.pack -instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word32)) (SimpleBalancedParens (DVS.Vector Word32))) where+instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word32)) (BP.SimpleBalancedParens (DVS.Vector Word32))) where fromString = fromByteString . BSC.pack -instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word64)) (SimpleBalancedParens (DVS.Vector Word64))) where+instance IsString (JsonCursor BS.ByteString (BitShown (DVS.Vector Word64)) (BP.SimpleBalancedParens (DVS.Vector Word64))) where fromString = fromByteString . BSC.pack -instance IsString (JsonCursor BS.ByteString Poppy512 (SimpleBalancedParens (DVS.Vector Word64))) where+instance IsString (JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))) where fromString = fromByteString . BSC.pack -instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word8)) (SimpleBalancedParens (DVS.Vector Word8))) where+instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word8)) (BP.SimpleBalancedParens (DVS.Vector Word8))) where fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (castForeignPtr fptr) offset size) -instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word16)) (SimpleBalancedParens (DVS.Vector Word16))) where+instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word16)) (BP.SimpleBalancedParens (DVS.Vector Word16))) where fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (castForeignPtr fptr) offset size) -instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word32)) (SimpleBalancedParens (DVS.Vector Word32))) where+instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word32)) (BP.SimpleBalancedParens (DVS.Vector Word32))) where fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (castForeignPtr fptr) offset size) -instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word64)) (SimpleBalancedParens (DVS.Vector Word64))) where+instance FromForeignRegion (JsonCursor BS.ByteString (BitShown (DVS.Vector Word64)) (BP.SimpleBalancedParens (DVS.Vector Word64))) where fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (castForeignPtr fptr) offset size) -instance FromForeignRegion (JsonCursor BS.ByteString Poppy512 (SimpleBalancedParens (DVS.Vector Word64))) where+instance FromForeignRegion (JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))) where fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (castForeignPtr fptr) offset size) instance (BP.BalancedParens u, Rank1 u, Rank0 u) => TreeCursor (JsonCursor t v u) where- firstChild :: JsonCursor t v u -> JsonCursor t v u- firstChild k = k { cursorRank = BP.firstChild (balancedParens k) (cursorRank k) }+ firstChild :: JsonCursor t v u -> Maybe (JsonCursor t v u)+ firstChild k = let mq = BP.firstChild (balancedParens k) (cursorRank k) in (\q -> k { cursorRank = q }) <$> mq - nextSibling :: JsonCursor t v u -> JsonCursor t v u- nextSibling k = k { cursorRank = BP.nextSibling (balancedParens k) (cursorRank k) }+ nextSibling :: JsonCursor t v u -> Maybe (JsonCursor t v u)+ nextSibling k = let mq = BP.nextSibling (balancedParens k) (cursorRank k) in (\q -> k { cursorRank = q }) <$> mq - parent :: JsonCursor t v u -> JsonCursor t v u- parent k = k { cursorRank = BP.parent (balancedParens k) (cursorRank k) }+ parent :: JsonCursor t v u -> Maybe (JsonCursor t v u)+ parent k = let mq = BP.parent (balancedParens k) (cursorRank k) in (\q -> k { cursorRank = q }) <$> mq depth :: JsonCursor t v u -> Count depth k = BP.depth (balancedParens k) (cursorRank k)@@ -111,31 +116,53 @@ wIsJsonNumberDigit :: Word8 -> Bool wIsJsonNumberDigit w = (w >= _0 && w <= _9) || w == _hyphen -instance TestBit w => JsonTypeAt (JsonCursor BS.ByteString v w) where- jsonTypeAtPosition p k = if balancedParens k .?. p- then case cursorText k !!! p of- c | c == _bracketleft -> Just JsonTypeArray- c | c == _t -> Just JsonTypeBool- c | c == _n -> Just JsonTypeNull- c | wIsJsonNumberDigit c -> Just JsonTypeNumber- c | c == _braceleft -> Just JsonTypeObject- c | c == _quotedbl -> Just JsonTypeString+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonTypeAt (JsonCursor BS.ByteString v w) where+ jsonTypeAtPosition p k = if bpk .?. p+ then case BS.uncons (vDrop (toCount p) (cursorText k)) of+ Just (c, _) | c == _bracketleft -> Just JsonTypeArray+ Just (c, _) | c == _t -> Just JsonTypeBool+ Just (c, _) | c == _n -> Just JsonTypeNull+ Just (c, _) | wIsJsonNumberDigit c -> Just JsonTypeNumber+ Just (c, _) | c == _braceleft -> Just JsonTypeObject+ Just (c, _) | c == _quotedbl -> Just JsonTypeString _ -> Nothing else Nothing+ where bpk = balancedParens k - jsonTypeAt k = jsonTypeAtPosition (lastPositionOf (cursorRank k)) k+ jsonTypeAt k = jsonTypeAtPosition p k+ where p = toPosition (select1 ik (rank1 bpk (cursorRank k)) - 1)+ ik = interests k+ bpk = balancedParens k -instance TestBit w => JsonValueAt BS.ByteString BS.ByteString (JsonCursor BS.ByteString v w) where+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonValueAt BS.ByteString BS.ByteString (JsonCursor BS.ByteString v w) where jsonValueAt :: JsonCursor BS.ByteString v w -> Maybe (JsonValue BS.ByteString BS.ByteString)- jsonValueAt k = case jsonTypeAtPosition p k of- Just JsonTypeArray -> error "Not Implemented"- Just JsonTypeBool -> case cursorText k !!! p of- c | c == _t -> Just $ JsonBool True- c | c == _t -> Just $ JsonBool False- _ -> Nothing- Just JsonTypeNull -> Just JsonNull- Just JsonTypeNumber -> error "Not Implemented"- Just JsonTypeObject -> error "Not Implemented"- Just JsonTypeString -> error "Not Implemented"- Nothing -> Nothing- where p = lastPositionOf (cursorRank k)+ jsonValueAt k = case extractJsonSnippet remainder of+ Just (JsonTypeArray , _) -> Just $ JsonArray (arrayValuesAt k)+ Just (JsonTypeBool , bs) -> case BS.uncons bs of+ Just (c, _) | c == _t -> Just $ JsonBool True+ Just (c, _) | c == _t -> Just $ JsonBool False+ _ -> Nothing+ Just (JsonTypeNull , _) -> Just JsonNull+ Just (JsonTypeNumber, bs) -> Just $ JsonNumber bs+ Just (JsonTypeObject, _) -> Just $ JsonObject (mapValuesAt k)+ Just (JsonTypeString, bs) -> Just $ JsonString bs+ Nothing -> Nothing+ where p = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))+ ik = interests k+ bpk = balancedParens k+ remainder = (vDrop (toCount p) (cursorText k))+ genArrayValue :: JsonCursor BS.ByteString v w -> Maybe (JsonValue ByteString ByteString, JsonCursor ByteString v w)+ genArrayValue j = (,) <$> jsonValueAt j <*> nextSibling j+ arrayValuesAt :: JsonCursor BS.ByteString v w -> [JsonValue BS.ByteString BS.ByteString]+ arrayValuesAt j = case firstChild j of+ Just c -> L.unfoldr genArrayValue c+ Nothing -> []+ mapValuesAt :: JsonCursor BS.ByteString v w -> M.Map ByteString (JsonValue ByteString ByteString)+ mapValuesAt j = M.fromList (pairwise (arrayValuesAt j) >>= asField)+ asField :: (JsonValue ByteString ByteString, JsonValue ByteString ByteString) -> [(ByteString, JsonValue ByteString ByteString)]+ asField (a, b) = case a of+ JsonString s -> [(s, b)]+ _ -> []+ pairwise :: [a] -> [(a, a)]+ pairwise (a:b:rs) = (a, b) : pairwise rs+ pairwise _ = []
test/HaskellWorks/Data/Json/Succinct/CursorSpec.hs view
@@ -11,7 +11,9 @@ module HaskellWorks.Data.Json.Succinct.CursorSpec(spec) where +import Control.Monad import qualified Data.ByteString as BS+import qualified Data.Map as M import Data.String import qualified Data.Vector.Storable as DVS import Data.Word@@ -21,6 +23,7 @@ import HaskellWorks.Data.FromForeignRegion import HaskellWorks.Data.Json.Succinct.Cursor as C import HaskellWorks.Data.Json.Token+import HaskellWorks.Data.Json.Value import HaskellWorks.Data.Succinct.BalancedParens.Internal import HaskellWorks.Data.Succinct.BalancedParens.Simple import HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0@@ -46,55 +49,55 @@ describe "Cursor for [Bool]" $ do it "initialises to beginning of empty object" $ do let cursor = "{}" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorObject+ jsonCursorType cursor `shouldBe` Just JsonCursorObject it "initialises to beginning of empty object preceded by spaces" $ do let cursor = " {}" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorObject+ jsonCursorType cursor `shouldBe` Just JsonCursorObject it "initialises to beginning of number" $ do let cursor = "1234" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorNumber+ jsonCursorType cursor `shouldBe` Just JsonCursorNumber it "initialises to beginning of string" $ do let cursor = "\"Hello\"" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorString+ jsonCursorType cursor `shouldBe` Just JsonCursorString it "initialises to beginning of array" $ do let cursor = "[]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorArray+ jsonCursorType cursor `shouldBe` Just JsonCursorArray it "initialises to beginning of boolean true" $ do let cursor = "true" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorBool+ jsonCursorType cursor `shouldBe` Just JsonCursorBool it "initialises to beginning of boolean false" $ do let cursor = "false" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorBool+ jsonCursorType cursor `shouldBe` Just JsonCursorBool it "initialises to beginning of null" $ do let cursor = "null" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType cursor `shouldBe` JsonCursorNull+ jsonCursorType cursor `shouldBe` Just JsonCursorNull it "cursor can navigate to first child of array" $ do let cursor = "[null]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType (fc cursor) `shouldBe` JsonCursorNull+ (fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorNull it "cursor can navigate to second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType ((ns . fc) cursor) `shouldBe` JsonCursorObject+ (fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorObject it "cursor can navigate to first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType ((fc . ns . fc) cursor) `shouldBe` JsonCursorString+ (fc >=> ns >=> fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString it "cursor can navigate to first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- jsonCursorType ((ns . fc . ns . fc) cursor) `shouldBe` JsonCursorNumber+ (fc >=> ns >=> fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorNumber it "depth at top" $ do let cursor = "[null]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool]) cd cursor `shouldBe` 1 it "depth at first child of array" $ do let cursor = "[null]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- cd (fc cursor) `shouldBe` 2+ cd <$> fc cursor `shouldBe` Just 2 it "depth at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- cd ((ns . fc) cursor) `shouldBe` 2+ cd <$> (fc >=> ns) cursor `shouldBe` Just 2 it "depth at first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- cd ((fc . ns . fc) cursor) `shouldBe` 3+ cd <$> (fc >=> ns >=> fc) cursor `shouldBe` Just 3 it "depth at first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor String (BitShown [Bool]) (SimpleBalancedParens [Bool])- cd ((ns . fc . ns . fc) cursor) `shouldBe` 3+ cd <$> (fc >=> ns >=> fc >=> ns) cursor `shouldBe` Just 3 genSpec "DVS.Vector Word8" (undefined :: JsonCursor BS.ByteString (BitShown (DVS.Vector Word8)) (SimpleBalancedParens (DVS.Vector Word8))) genSpec "DVS.Vector Word16" (undefined :: JsonCursor BS.ByteString (BitShown (DVS.Vector Word16)) (SimpleBalancedParens (DVS.Vector Word16))) genSpec "DVS.Vector Word32" (undefined :: JsonCursor BS.ByteString (BitShown (DVS.Vector Word32)) (SimpleBalancedParens (DVS.Vector Word32)))@@ -131,121 +134,124 @@ , TestBit u , FromForeignRegion (JsonCursor BS.ByteString t u) , IsString (JsonCursor BS.ByteString t u)- , HasJsonCursorType (JsonCursor BS.ByteString t u))+ , HasJsonCursorType (JsonCursor BS.ByteString t u)+ , JsonValueAt BS.ByteString BS.ByteString (JsonCursor BS.ByteString t u)) => String -> (JsonCursor BS.ByteString t u) -> SpecWith () genSpec t _ = do describe ("Cursor for (" ++ t ++ ")") $ do it "initialises to beginning of empty object" $ do let cursor = "{}" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorObject+ jsonCursorType cursor `shouldBe` Just JsonCursorObject it "initialises to beginning of empty object preceded by spaces" $ do let cursor = " {}" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorObject+ jsonCursorType cursor `shouldBe` Just JsonCursorObject+ jsonValueAt cursor `shouldBe` Just (JsonObject M.empty :: JsonValue BS.ByteString BS.ByteString) it "initialises to beginning of number" $ do let cursor = "1234" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorNumber+ jsonCursorType cursor `shouldBe` Just JsonCursorNumber it "initialises to beginning of string" $ do let cursor = "\"Hello\"" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorString+ jsonCursorType cursor `shouldBe` Just JsonCursorString it "initialises to beginning of array" $ do let cursor = "[]" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorArray+ jsonCursorType cursor `shouldBe` Just JsonCursorArray+ jsonValueAt cursor `shouldBe` Just (JsonArray [] :: JsonValue BS.ByteString BS.ByteString) it "initialises to beginning of boolean true" $ do let cursor = "true" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorBool+ jsonCursorType cursor `shouldBe` Just JsonCursorBool it "initialises to beginning of boolean false" $ do let cursor = "false" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorBool+ jsonCursorType cursor `shouldBe` Just JsonCursorBool it "initialises to beginning of null" $ do let cursor = "null" :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorNull+ jsonCursorType cursor `shouldBe` Just JsonCursorNull it "cursor can navigate to first child of array" $ do let cursor = "[null]" :: JsonCursor BS.ByteString t u- jsonCursorType (fc cursor) `shouldBe` JsonCursorNull+ (fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorNull it "cursor can navigate to second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor BS.ByteString t u- jsonCursorType ((ns . fc) cursor) `shouldBe` JsonCursorObject+ (fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorObject it "cursor can navigate to first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor BS.ByteString t u- jsonCursorType ((fc . ns . fc) cursor) `shouldBe` JsonCursorString+ (fc >=> ns >=> fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString it "cursor can navigate to first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor BS.ByteString t u- jsonCursorType ((ns . fc . ns . fc) cursor) `shouldBe` JsonCursorNumber+ (fc >=> ns >=> fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorNumber it "depth at top" $ do let cursor = "[null]" :: JsonCursor BS.ByteString t u cd cursor `shouldBe` 1 it "depth at first child of array" $ do let cursor = "[null]" :: JsonCursor BS.ByteString t u- cd (fc cursor) `shouldBe` 2+ cd <$> (fc) cursor `shouldBe` Just 2 it "depth at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor BS.ByteString t u- cd ((ns . fc) cursor) `shouldBe` 2+ cd <$> (fc >=> ns) cursor `shouldBe` Just 2 it "depth at first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor BS.ByteString t u- cd ((fc . ns . fc) cursor) `shouldBe` 3+ cd <$> (fc >=> ns >=> fc) cursor `shouldBe` Just 3 it "depth at first child of object at second child of array" $ do let cursor = "[null, {\"field\": 1}]" :: JsonCursor BS.ByteString t u- cd ((ns . fc . ns . fc) cursor) `shouldBe` 3+ cd <$> (fc >=> ns >=> fc >=> ns) cursor `shouldBe` Just 3 it "can navigate down and forwards" $ do (fptr, offset, size) <- mmapFileForeignPtr "test/data/sample.json" ReadOnly Nothing let cursor = fromForeignRegion (fptr, offset, size) :: JsonCursor BS.ByteString t u- jsonCursorType cursor `shouldBe` JsonCursorObject- jsonCursorType (( fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . fc) cursor) `shouldBe` JsonCursorObject- jsonCursorType (( fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorObject- jsonCursorType (( fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType (( ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorString- jsonCursorType ((ns . ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` JsonCursorNumber+ (jsonCursorType ) cursor `shouldBe` Just JsonCursorObject+ (fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorObject+ (fc >=> ns >=> fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorObject+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorString+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> ns >=> jsonCursorType) cursor `shouldBe` Just JsonCursorNumber it "can navigate up" $ do (fptr, offset, size) <- mmapFileForeignPtr "test/data/sample.json" ReadOnly Nothing let cursor = fromForeignRegion (fptr, offset, size) :: JsonCursor BS.ByteString t u- ( pn . fc) cursor `shouldBe` cursor- ( pn . ns . fc) cursor `shouldBe` cursor- ( pn . fc . ns . fc) cursor `shouldBe` ( ns . fc) cursor- ( pn . ns . fc . ns . fc) cursor `shouldBe` ( ns . fc) cursor- ( pn . ns . ns . fc . ns . fc) cursor `shouldBe` ( ns . fc) cursor- ( pn . ns . ns . ns . fc . ns . fc) cursor `shouldBe` ( ns . fc) cursor- ( pn . fc . ns . ns . ns . fc . ns . fc) cursor `shouldBe` (ns . ns . ns . fc . ns . fc) cursor- ( pn . ns . fc . ns . ns . ns . fc . ns . fc) cursor `shouldBe` (ns . ns . ns . fc . ns . fc) cursor- ( pn . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor `shouldBe` (ns . ns . ns . fc . ns . fc) cursor- ( pn . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor `shouldBe` (ns . ns . ns . fc . ns . fc) cursor- ( pn . ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor `shouldBe` (ns . ns . ns . fc . ns . fc) cursor- ( pn . ns . ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor `shouldBe` (ns . ns . ns . fc . ns . fc) cursor+ (fc >=> pn ) cursor `shouldBe` Just cursor+ (fc >=> ns >=> pn ) cursor `shouldBe` Just cursor+ (fc >=> ns >=> fc >=> pn ) cursor `shouldBe` (fc >=> ns ) cursor+ (fc >=> ns >=> fc >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns ) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns ) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns ) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> pn ) cursor `shouldBe` (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> pn ) cursor `shouldBe` (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> ns >=> pn) cursor `shouldBe` (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor it "can get subtree size" $ do (fptr, offset, size) <- mmapFileForeignPtr "test/data/sample.json" ReadOnly Nothing let cursor = fromForeignRegion (fptr, offset, size) :: JsonCursor BS.ByteString t u- ss cursor `shouldBe` 45- ss (( fc) cursor) `shouldBe` 1- ss (( ns . fc) cursor) `shouldBe` 43- ss (( fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . ns . fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 9- ss (( fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 1- ss (( ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 1- ss ((ns . ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` 1+ ss cursor `shouldBe` 45+ ss <$> (fc ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns ) cursor `shouldBe` Just 43+ ss <$> (fc >=> ns >=> fc ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns ) cursor `shouldBe` Just 9+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns ) cursor `shouldBe` Just 1+ ss <$> (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> ns ) cursor `shouldBe` Just 1 it "can get token at cursor" $ do (fptr, offset, size) <- mmapFileForeignPtr "test/data/sample.json" ReadOnly Nothing let cursor = fromForeignRegion (fptr, offset, size) :: JsonCursor BS.ByteString t u- jsonTokenAt cursor `shouldBe` Just (JsonTokenBraceL )- jsonTokenAt (( fc) cursor) `shouldBe` Just (JsonTokenString "widget" )- jsonTokenAt (( ns . fc) cursor) `shouldBe` Just (JsonTokenBraceL )- jsonTokenAt (( fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "debug" )- jsonTokenAt (( ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "on" )- jsonTokenAt (( ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "window" )- jsonTokenAt (( ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenBraceL )- jsonTokenAt (( fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "title" )- jsonTokenAt (( ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "Sample Konfabulator Widget")- jsonTokenAt (( ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "name" )- jsonTokenAt (( ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "main_window" )- jsonTokenAt (( ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenString "width" )- jsonTokenAt ((ns . ns . ns . ns . ns . fc . ns . ns . ns . fc . ns . fc) cursor) `shouldBe` Just (JsonTokenNumber 500.0 )+ (jsonTokenAt ) cursor `shouldBe` Just (JsonTokenBraceL )+ (fc >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "widget" )+ (fc >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenBraceL )+ (fc >=> ns >=> fc >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "debug" )+ (fc >=> ns >=> fc >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "on" )+ (fc >=> ns >=> fc >=> ns >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "window" )+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenBraceL )+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "title" )+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "Sample Konfabulator Widget")+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "name" )+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "main_window" )+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenString "width" )+ (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns >=> ns >=> jsonTokenAt) cursor `shouldBe` Just (JsonTokenNumber 500.0 )