diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
 # hw-json
+
 [![master](https://circleci.com/gh/haskell-works/hw-json/tree/master.svg?style=svg)](https://circleci.com/gh/haskell-works/hw-json/tree/master)
 
 `hw-json` is a succinct JSON parsing library.
@@ -10,9 +11,19 @@
 ## Prerequisites
 
 * `cabal` version `2.2` or later
+* Depending on your use case you may need additional package dependencies.  These can be found in the library dependencies of the examples
+  library component in the cabal file.
 
 ## Memory benchmark
 
+If you need a repl to run any of the Haskell examples in this README, please run the command:
+
+```bash
+cabal v2-repl lib:examples
+```
+
+For rexamples these examples are also found in Haskell modules under the `examples` directory.
+
 ### Parsing large Json files in Scala with Argonaut
 
 ```text
@@ -34,12 +45,11 @@
 ```haskell
 -- CMD                                                     -- Mem (MB)
 ---------------------------------------------------------- -- --------
-import Control.DeepSeq                                     --       94
-import Data.Aeson                                          --      100
-import qualified Data.ByteString.Lazy as BSL               --      104
-bs <- BSL.readFile "../corpus/bench/hospitalisation.json"  --      105
-let !x = deepseq bs bs                                     --      146
-let !y = decode json78m :: Maybe Value                     --      669
+import Control.DeepSeq                                     --      345
+import Data.Aeson                                          --      371
+import qualified Data.ByteString.Lazy as LBS               --      376
+!bs <- LBS.readFile "corpus/bench/hospitalisation.json"    --      380
+let !y = decode bs :: Maybe Value                          --      928
 ```
 
 ### Parsing large Json files in Haskell with hw-json
@@ -47,20 +57,12 @@
 ```haskell
 -- CMD                                                                -- Mem (MB)
 --------------------------------------------------------------------- -- --------
-import Foreign                                                        --       93
-import Control.Monad                                                  --       95
-import Data.Word                                                      --       96
-import HaskellWorks.Data.BalancedParens.Simple                        --       97
-import HaskellWorks.Data.Bits.BitShown                                --       98
-import HaskellWorks.Data.FromForeignRegion                            --       99
-import HaskellWorks.Data.Json.Backend.Standard.Cursor                 --      106
-import System.IO.MMap                                                 --      109
-import qualified Data.ByteString                              as BS   --      110
-import qualified Data.Vector.Storable                         as DVS  --      111
-import qualified HaskellWorks.Data.ByteString                 as BS   --      112
-import qualified HaskellWorks.Data.Json.Backend.Standard.Fast as FAST --      114
-bs <- BS.mmap "../corpus/bench/hospitalisation.json"                  --      115
-let !cursor = FAST.makeCursor bs                                      --      203
+import qualified HaskellWorks.Data.ByteString                as BS    --      351
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as JCF   --      353
+
+!jsonBs <- BS.mmap "corpus/bench/hospitalisation.json"                --      355
+let !ibip = JCF.simdToIbBp jsonBs                                     --      358
+let !c    = JCF.fromBsIbBp jsonBs ibip                                --      495
 ```
 
 ## Examples
@@ -69,32 +71,18 @@
 
 ```haskell
 import Control.Monad
-import Data.String
-import Data.Word
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Bits.BitShow
-import HaskellWorks.Data.Bits.BitShown
-import HaskellWorks.Data.FromForeignRegion
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Internal.Token.Types
-import HaskellWorks.Data.RankSelect.Base.Rank0
-import HaskellWorks.Data.RankSelect.Base.Rank1
-import HaskellWorks.Data.RankSelect.Base.Select1
-import HaskellWorks.Data.RankSelect.Poppy512
-import System.IO.MMap
 
-import qualified Data.ByteString                                as BS
-import qualified Data.Vector.Storable                           as DVS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Cursor as C
-import qualified HaskellWorks.Data.Json.Backend.Standard.Fast   as FAST
-import qualified HaskellWorks.Data.TreeCursor                   as TC
+import qualified Data.ByteString                             as BS
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as JCF
+import qualified HaskellWorks.Data.TreeCursor                as TC
 
 let fc = TC.firstChild
 let ns = TC.nextSibling
 let pn = TC.parent
 let ss = TC.subtreeSize
-let cursor = FAST.makeCursor "[null, {\"field\": 1}]"
-cursor
+let jsonBs  = "[null, {\"field\": 1}]" :: BS.ByteString
+let ibip    = JCF.simdToIbBp jsonBs
+let cursor  = JCF.fromBsIbBp jsonBs ibip
 fc cursor
 (fc >=> ns) cursor
 ```
@@ -105,20 +93,18 @@
 import Control.Monad
 import Data.Function
 import Data.List
-import HaskellWorks.Data.Json.Backend.Standard.Load.Cursor
-import HaskellWorks.Data.Json.Backend.Standard.Load.Partial
-import HaskellWorks.Data.Json.Backend.Standard.Load.Raw
 import HaskellWorks.Data.Json.PartialValue
+import HaskellWorks.Data.Json.Standard.Cursor.Load.Cursor
+import HaskellWorks.Data.Json.Standard.Load.Partial
 import HaskellWorks.Data.MQuery
 import HaskellWorks.Data.MQuery.Micro
-import HaskellWorks.Data.MQuery.Row
 
 import qualified Data.DList as DL
 
-!cursor <- loadPartial "../corpus/bench/78mb.json"
-!cursor <- loadCursorWithIndex "../corpus/bench/78mb.json"
-!cursor <- loadCursor "../corpus/bench/78mb.json"
-!cursor <- loadCursorWithCsPoppyIndex "../corpus/bench/78mb.json"
+!cursor <- loadPartial "corpus/bench/78mb.json"
+!cursor <- loadCursorWithIndex "corpus/bench/78mb.json"
+!cursor <- loadCursor "corpus/bench/78mb.json"
+!cursor <- loadCursorWithCsPoppyIndex "corpus/bench/78mb.json"
 let !json = jsonPartialJsonValueAt cursor
 let q = MQuery (DL.singleton json)
 
diff --git a/app/App/Commands.hs b/app/App/Commands.hs
--- a/app/App/Commands.hs
+++ b/app/App/Commands.hs
@@ -1,10 +1,13 @@
 module App.Commands where
 
+import App.Commands.Count
+import App.Commands.CountAeson
 import App.Commands.CreateIndex
 import App.Commands.Demo
-import Data.Semigroup           ((<>))
 import Options.Applicative
 
+{- HLINT ignore "Monoid law, left identity" -}
+
 commands :: Parser (IO ())
 commands = commandsGeneral
 
@@ -12,4 +15,6 @@
 commandsGeneral = subparser $ mempty
   <>  commandGroup "Commands:"
   <>  cmdCreateIndex
+  <>  cmdCount
+  <>  cmdCountAeson
   <>  cmdDemo
diff --git a/app/App/Commands/Count.hs b/app/App/Commands/Count.hs
new file mode 100644
--- /dev/null
+++ b/app/App/Commands/Count.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+module App.Commands.Count
+  ( cmdCount
+  ) where
+
+import Control.Lens
+import Control.Monad
+import Data.Generics.Product.Any
+import Data.Word
+import HaskellWorks.Data.FromForeignRegion
+import HaskellWorks.Data.Json.LightJson
+import HaskellWorks.Data.Json.Query
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.MQuery
+import HaskellWorks.Data.MQuery.Micro
+import HaskellWorks.Data.RankSelect.CsPoppy1
+import HaskellWorks.Data.TreeCursor
+import Options.Applicative                            hiding (columns)
+
+import qualified App.Commands.Types                          as Z
+import qualified Data.ByteString                             as BS
+import qualified Data.ByteString.Internal                    as BSI
+import qualified Data.DList                                  as DL
+import qualified Data.Vector.Storable                        as DVS
+import qualified HaskellWorks.Data.BalancedParens.RangeMin   as RM
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as JCF
+import qualified System.IO.MMap                              as IO
+
+siblings :: GenericCursor BSI.ByteString CsPoppy1 (RM.RangeMin CsPoppy1) -> [GenericCursor BSI.ByteString CsPoppy1 (RM.RangeMin CsPoppy1)]
+siblings c = c:maybe [] siblings (nextSibling c)
+
+runCount :: Z.CountOptions -> IO ()
+#if aarch64_HOST_ARCH
+runCount = undefined
+#else
+runCount opts = do
+  let inputFile   = opts ^. the @"inputFile"
+  let expression  = opts ^. the @"expression"
+  jsonFr    <- IO.mmapFileForeignPtr inputFile IO.ReadOnly Nothing
+  let jsonBs  = fromForeignRegion jsonFr    :: BS.ByteString
+
+  cursor <- case opts ^. the @"indexes" of
+    Just indexes -> do
+      let ibIndex     = indexes ^. the @"ibIndex"
+      let bpIndex     = indexes ^. the @"bpIndex"
+      jsonIbFr  <- IO.mmapFileForeignPtr ibIndex   IO.ReadOnly Nothing
+      jsonBpFr  <- IO.mmapFileForeignPtr bpIndex   IO.ReadOnly Nothing
+      let jsonIb  = fromForeignRegion jsonIbFr  :: DVS.Vector Word64
+      let jsonBp  = fromForeignRegion jsonBpFr  :: DVS.Vector Word64
+
+      return $ GenericCursor jsonBs (makeCsPoppy jsonIb) (RM.mkRangeMin (makeCsPoppy jsonBp)) 1
+    Nothing -> do
+      let !ibip = JCF.simdToIbBp jsonBs
+      let !c    = JCF.fromBsIbBp jsonBs ibip
+      return c
+
+  let q = MQuery (DL.fromList $ fmap lightJsonAt (siblings cursor))
+
+  putPretty $ q >>= (entry >=> named expression) & count
+
+  return ()
+#endif
+
+optsFileIndex :: Parser Z.FileIndexes
+optsFileIndex = Z.FileIndexes
+  <$> strOption
+    (   long "ib-index"
+    <>  help "IB index"
+    <>  metavar "FILE"
+    )
+  <*> strOption
+    (   long "bp-index"
+    <>  help "BP index"
+    <>  metavar "FILE"
+    )
+
+optsCount :: Parser Z.CountOptions
+optsCount = Z.CountOptions
+  <$> strOption
+        (   long "input"
+        <>  short 'i'
+        <>  help "Input JSON file"
+        <>  metavar "FILE"
+        )
+  <*> optional optsFileIndex
+  <*> strOption
+        (   long "expression"
+        <>  help "JSON expression"
+        <>  metavar "EXPRESSION"
+        )
+
+cmdCount :: Mod CommandFields (IO ())
+cmdCount = command "count"  $ flip info idm $ runCount <$> optsCount
diff --git a/app/App/Commands/CountAeson.hs b/app/App/Commands/CountAeson.hs
new file mode 100644
--- /dev/null
+++ b/app/App/Commands/CountAeson.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+module App.Commands.CountAeson
+  ( cmdCountAeson
+  ) where
+
+import Control.Lens
+import Data.Generics.Product.Any
+import Options.Applicative       hiding (columns)
+
+import qualified App.Commands.Types   as Z
+import qualified Data.Aeson           as J
+import qualified Data.Aeson.Key       as J
+import qualified Data.Aeson.KeyMap    as J
+import qualified Data.ByteString.Lazy as LBS
+import qualified System.IO            as IO
+
+runCountAeson :: Z.CountAesonOptions -> IO ()
+runCountAeson opts = do
+  let inputFile   = opts ^. the @"inputFile"
+  let expression  = opts ^. the @"expression"
+
+  lbs <- LBS.readFile inputFile
+
+  let lbsLines = LBS.split 10 lbs
+
+  let count :: Int = sum $ flip fmap lbsLines $ \lbsLine -> case J.decode lbsLine of
+        Just (J.Object v) -> if J.member (J.fromText expression) v then 1 else 0
+        _                 -> 0
+
+  IO.putStrLn $ "Count: " <> show count
+
+  return ()
+
+optsCountAeson :: Parser Z.CountAesonOptions
+optsCountAeson = Z.CountAesonOptions
+  <$> strOption
+        (   long "input"
+        <>  short 'i'
+        <>  help "Input JSON file"
+        <>  metavar "FILE"
+        )
+  <*> strOption
+        (   long "expression"
+        <>  help "JSON expression"
+        <>  metavar "EXPRESSION"
+        )
+
+cmdCountAeson :: Mod CommandFields (IO ())
+cmdCountAeson = command "count-aeson"  $ flip info idm $ runCountAeson <$> optsCountAeson
diff --git a/app/App/Commands/CreateIndex.hs b/app/App/Commands/CreateIndex.hs
--- a/app/App/Commands/CreateIndex.hs
+++ b/app/App/Commands/CreateIndex.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
@@ -11,32 +12,34 @@
 import Control.Monad
 import Data.Generics.Product.Any
 import Data.Maybe
-import Data.Semigroup            ((<>))
 import Data.Word
 import Foreign
 import Options.Applicative       hiding (columns)
 
-import qualified App.Commands.Types                                                  as Z
-import qualified Data.ByteString                                                     as BS
-import qualified Data.ByteString.Internal                                            as BSI
-import qualified Data.ByteString.Lazy                                                as LBS
-import qualified HaskellWorks.Data.ByteString                                        as BS
-import qualified HaskellWorks.Data.ByteString.Lazy                                   as LBS
-import qualified HaskellWorks.Data.Json.Backend.Simple.SemiIndex                     as SISI
-import qualified HaskellWorks.Data.Json.Backend.Standard.SemiIndex                   as STSI
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.Blank              as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson        as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex          as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.ToBalancedParens64 as J
-import qualified HaskellWorks.Data.Json.Simd.Index.Standard                          as STSI
-import qualified System.Exit                                                         as IO
-import qualified System.IO                                                           as IO
-import qualified System.IO.MMap                                                      as IO
+import qualified App.Commands.Types                                                 as Z
+import qualified Data.ByteString                                                    as BS
+import qualified Data.ByteString.Internal                                           as BSI
+import qualified Data.ByteString.Lazy                                               as LBS
+import qualified HaskellWorks.Data.ByteString                                       as BS
+import qualified HaskellWorks.Data.ByteString.Lazy                                  as LBS
+#if x86_64_HOST_ARCH
+import qualified HaskellWorks.Data.Json.Simd.Index.Standard                         as STSI
+#endif
+import qualified HaskellWorks.Data.Json.Simple.Cursor.SemiIndex                     as SISI
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Internal.Blank              as J
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Internal.BlankedJson        as J
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Internal.MakeIndex          as J
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Internal.ToBalancedParens64 as J
+import qualified HaskellWorks.Data.Json.Standard.Cursor.SemiIndex                   as STSI
+import qualified System.Exit                                                        as IO
+import qualified System.IO                                                          as IO
+import qualified System.IO.MMap                                                     as IO
 
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant do"       -}
 
 runCreateIndexStandard :: Z.CreateIndexOptions -> IO ()
+#if x86_64_HOST_ARCH
 runCreateIndexStandard opts = do
   let filePath = opts ^. the @"filePath"
   let outputIbFile = opts ^. the @"outputIbFile" & fromMaybe (filePath <> ".ib.idx")
@@ -81,8 +84,12 @@
     unknown -> do
       IO.hPutStrLn IO.stderr $ "Unknown method " <> show unknown
       IO.exitFailure
+#else
+runCreateIndexStandard opts = undefined
+#endif
 
 runCreateIndexSimple :: Z.CreateIndexOptions -> IO ()
+#if x86_64_HOST_ARCH
 runCreateIndexSimple opts = do
   let filePath = opts ^. the @"filePath"
   let outputIbFile = opts ^. the @"outputIbFile" & fromMaybe (filePath <> ".ib.idx")
@@ -92,6 +99,9 @@
   let SISI.SemiIndex _ ibs bps = SISI.buildSemiIndex bs
   LBS.writeFile outputIbFile (LBS.toLazyByteString ibs)
   LBS.writeFile outputBpFile (LBS.toLazyByteString bps)
+#else
+runCreateIndexSimple opts = undefined
+#endif
 
 runCreateIndex :: Z.CreateIndexOptions -> IO ()
 runCreateIndex opts = case opts ^. the @"backend" of
diff --git a/app/App/Commands/Demo.hs b/app/App/Commands/Demo.hs
--- a/app/App/Commands/Demo.hs
+++ b/app/App/Commands/Demo.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -10,58 +11,36 @@
 
 import Control.Lens
 import Control.Monad
-import Control.Monad.ST
 import Data.Generics.Product.Any
-import Data.Semigroup                                      ((<>))
 import Data.Word
 import Foreign.ForeignPtr
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Backend.Standard.Load.Cursor
 import HaskellWorks.Data.Json.LightJson
 import HaskellWorks.Data.Json.Query
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Json.Standard.Cursor.Load.Cursor
 import HaskellWorks.Data.MQuery
 import HaskellWorks.Data.MQuery.Micro
 import HaskellWorks.Data.RankSelect.CsPoppy
-import HaskellWorks.Data.Vector.AsVector8
-import Options.Applicative                                 hiding (columns)
+import HaskellWorks.Data.Vector.Storable
+import Options.Applicative                                hiding (columns)
 
 import qualified App.Commands.Types                         as Z
-import qualified Data.ByteString                            as BS
 import qualified Data.ByteString.Internal                   as BSI
 import qualified Data.ByteString.Lazy                       as LBS
 import qualified Data.DList                                 as DL
-import qualified Data.Vector.Storable                       as DVS
-import qualified Data.Vector.Storable.Mutable               as DVSM
+import qualified HaskellWorks.Data.BalancedParens.RangeMin  as RM
 import qualified HaskellWorks.Data.ByteString.Lazy          as LBS
+#if x86_64_HOST_ARCH
 import qualified HaskellWorks.Data.Json.Simd.Index.Standard as S
+#endif
 import qualified Options.Applicative                        as OA
 import qualified System.IO                                  as IO
 import qualified System.IO.MMap                             as IO
 
-constructUnzipN :: Int -> [(BS.ByteString, BS.ByteString)] -> (DVS.Vector Word64, DVS.Vector Word64)
-constructUnzipN nBytes xs = (DVS.unsafeCast ibv, DVS.unsafeCast bpv)
-  where [ibv, bpv] = DVS.createT $ do
-          let nW64s     = (nBytes + 7) `div` 8
-          let capacity  = nW64s * 8
-          ibmv <- DVSM.new capacity
-          bpmv <- DVSM.new capacity
-          (ibmvRemaining, bpmvRemaining) <- go ibmv bpmv xs
-          return
-            [ DVSM.take (((DVSM.length ibmv - ibmvRemaining) `div` 8) * 8) ibmv
-            , DVSM.take (((DVSM.length bpmv - bpmvRemaining) `div` 8) * 8) bpmv
-            ]
-        go :: DVSM.MVector s Word8 -> DVSM.MVector s Word8 -> [(BS.ByteString, BS.ByteString)] -> ST s (Int, Int)
-        go ibmv bpmv ((ib, bp):ys) = do
-          DVS.copy (DVSM.take (BS.length ib) ibmv) (asVector8 ib)
-          DVS.copy (DVSM.take (BS.length bp) bpmv) (asVector8 bp)
-          go (DVSM.drop (BS.length ib) ibmv) (DVSM.drop (BS.length bp) bpmv) ys
-        go ibmv bpmv [] = do
-          DVSM.set (DVSM.take 8 ibmv) 0
-          DVSM.set (DVSM.take 8 bpmv) 0
-          return (DVSM.length (DVSM.drop 8 ibmv), DVSM.length (DVSM.drop 8 bpmv))
+{- HLINT ignore "Reduce duplication" -}
 
 runDemo :: Z.DemoOptions -> IO ()
+#if x86_64_HOST_ARCH
 runDemo opts = do
   let filePath = opts ^. the @"filePath"
   case opts ^. the @"method" of
@@ -76,15 +55,17 @@
       let !bs = BSI.fromForeignPtr (castForeignPtr fptr) offset size
       case S.makeStandardJsonIbBps (LBS.resegmentPadded 512 (LBS.fromStrict bs)) of
         Right ibBps -> do
-          let (!ib, !bp) = constructUnzipN size ibBps
-          let !cursor = JsonCursor bs (makeCsPoppy ib) (SimpleBalancedParens bp) 1
+          let (!ib, !bp) = construct64UnzipN size ibBps
+          let !cursor = GenericCursor bs (makeCsPoppy ib) (RM.mkRangeMin bp) 1
           let !json = lightJsonAt cursor
           let q = MQuery (DL.singleton json)
 
           putPretty $ q >>= (entry >=> named "meta" >=> entry >=> named "view" >=> entry >=> named "columns" >=> item >=> entry >=> named "id") & count
         Left msg -> IO.hPutStrLn IO.stderr $ "Unable to create semi-index: " <> show msg
     m -> IO.hPutStrLn IO.stderr $ "Unrecognised method: " <> show m
-
+#else
+runDemo opts = undefined
+#endif
 
 optsDemo :: Parser Z.DemoOptions
 optsDemo = Z.DemoOptions
diff --git a/app/App/Commands/Types.hs b/app/App/Commands/Types.hs
--- a/app/App/Commands/Types.hs
+++ b/app/App/Commands/Types.hs
@@ -2,10 +2,14 @@
 {-# LANGUAGE DuplicateRecordFields #-}
 
 module App.Commands.Types
-  ( CreateIndexOptions(..)
+  ( CountAesonOptions(..)
+  , CountOptions(..)
+  , CreateIndexOptions(..)
   , DemoOptions(..)
+  , FileIndexes(..)
   ) where
 
+import Data.Text    (Text)
 import GHC.Generics
 
 data CreateIndexOptions = CreateIndexOptions
@@ -19,4 +23,20 @@
 data DemoOptions = DemoOptions
   { filePath :: FilePath
   , method   :: FilePath
+  } deriving (Eq, Show, Generic)
+
+data CountOptions = CountOptions
+  { inputFile  :: FilePath
+  , indexes    :: Maybe FileIndexes
+  , expression :: Text
+  } deriving (Eq, Show, Generic)
+
+data CountAesonOptions = CountAesonOptions
+  { inputFile  :: FilePath
+  , expression :: Text
+  } deriving (Eq, Show, Generic)
+
+data FileIndexes = FileIndexes
+  { ibIndex :: FilePath
+  , bpIndex :: FilePath
   } deriving (Eq, Show, Generic)
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -2,7 +2,6 @@
 
 import App.Commands
 import Control.Monad
-import Data.Semigroup      ((<>))
 import Options.Applicative
 
 main :: IO ()
diff --git a/bench/Main.hs b/bench/Main.hs
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -1,74 +1,10 @@
-{-# LANGUAGE BangPatterns        #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Main where
 
-import Control.Monad
 import Criterion.Main
-import Data.List
-import Data.Word
-import Foreign
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Blank
-import HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex
-import System.IO.MMap
 
-import qualified Data.ByteString                              as BS
-import qualified Data.ByteString.Internal                     as BSI
-import qualified HaskellWorks.Data.Json.Backend.Standard.Fast as FAST
-import qualified HaskellWorks.Data.Json.Backend.Standard.Slow as SLOW
-import qualified System.Directory                             as IO
-
-setupEnvJson :: FilePath -> IO BS.ByteString
-setupEnvJson filepath = do
-  (fptr :: ForeignPtr Word8, offset, size) <- mmapFileForeignPtr filepath ReadOnly Nothing
-  let !bs = BSI.fromForeignPtr (castForeignPtr fptr) offset size
-  return bs
-
-jsonToInterestBits3 :: [BS.ByteString] -> [BS.ByteString]
-jsonToInterestBits3 = blankedJsonToInterestBits . blankJson
-
-makeBenchBlankJson :: IO [Benchmark]
-makeBenchBlankJson = do
-  entries <- IO.listDirectory "corpus/bench"
-  let files = ("corpus/bench/" ++) <$> (".json" `isSuffixOf`) `filter` entries
-  benchmarks <- forM files $ \file -> return
-    [ env (setupEnvJson file) $ \bs -> bgroup file
-      [ bench "Run blankJson" (whnf (BS.concat . blankJson) [bs])
-      ]
-    ]
-
-  return (join benchmarks)
-
-makeBenchJsonToInterestBits :: IO [Benchmark]
-makeBenchJsonToInterestBits = do
-  entries <- IO.listDirectory "corpus/bench"
-  let files = ("corpus/bench/" ++) <$> (".json" `isSuffixOf`) `filter` entries
-  benchmarks <- forM files $ \file -> return
-    [ env (setupEnvJson file) $ \bs -> bgroup file
-      [ bench "Run blankJson" (whnf (BS.concat . jsonToInterestBits3) [bs])
-      ]
-    ]
-
-  return (join benchmarks)
-
-makeBenchMakeCursor :: IO [Benchmark]
-makeBenchMakeCursor = do
-  entries <- IO.listDirectory "corpus/bench"
-  let files = ("corpus/bench/" ++) <$> (".json" `isSuffixOf`) `filter` entries
-  benchmarks <- forM files $ \file -> return
-    [ env (setupEnvJson file) $ \bs -> bgroup file
-      [ bench "Run slow make cursor" (whnf SLOW.makeCursor bs)
-      , bench "Run fast make cursor" (whnf FAST.makeCursor bs)
-      ]
-    ]
-
-  return (join benchmarks)
-
 main :: IO ()
 main = do
-  benchmarks <- mconcat <$> sequence
-    [ makeBenchBlankJson
-    , makeBenchJsonToInterestBits
-    , makeBenchMakeCursor
-    ]
+  benchmarks <- mconcat <$> sequence mempty
   defaultMain benchmarks
diff --git a/doctest/DoctestDriver.hs b/doctest/DoctestDriver.hs
new file mode 100644
--- /dev/null
+++ b/doctest/DoctestDriver.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE CPP #-}
+
+#if MIN_VERSION_GLASGOW_HASKELL(8,4,4,0)
+{-# OPTIONS_GHC -F -pgmF doctest-discover #-}
+#else
+module Main where
+
+import qualified System.IO as IO
+
+main :: IO ()
+main = IO.putStrLn "WARNING: doctest will not run on GHC versions earlier than 8.4.4"
+#endif
diff --git a/examples/Example1.hs b/examples/Example1.hs
new file mode 100644
--- /dev/null
+++ b/examples/Example1.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE BangPatterns #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-matches     #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing     #-}
+{-# OPTIONS_GHC -fno-warn-unused-local-binds #-}
+
+module Example1 where
+
+import Data.Aeson
+
+import qualified Data.ByteString.Lazy as LBS
+
+example :: IO ()
+example = do
+  !bs <- LBS.readFile "corpus/bench/hospitalisation.json"
+  let !y = decode bs :: Maybe Value
+  return ()
diff --git a/examples/Example2.hs b/examples/Example2.hs
new file mode 100644
--- /dev/null
+++ b/examples/Example2.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE BangPatterns #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-matches     #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing     #-}
+{-# OPTIONS_GHC -fno-warn-unused-local-binds #-}
+
+module Example2 where
+
+import qualified HaskellWorks.Data.ByteString                as BS
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as JCF
+
+example :: IO ()
+example = do
+  !jsonBs <- BS.mmap "corpus/bench/hospitalisation.json"
+  let !ibip = JCF.simdToIbBp jsonBs
+  let !c    = JCF.fromBsIbBp jsonBs ibip
+  return ()
diff --git a/examples/Example3.hs b/examples/Example3.hs
new file mode 100644
--- /dev/null
+++ b/examples/Example3.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-matches     #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing     #-}
+{-# OPTIONS_GHC -fno-warn-unused-local-binds #-}
+
+module Example3 where
+
+import Control.Monad
+
+import qualified Data.ByteString                             as BS
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as JCF
+import qualified HaskellWorks.Data.TreeCursor                as TC
+
+example :: IO ()
+example = do
+  let fc = TC.firstChild
+  let ns = TC.nextSibling
+  let jsonBs  = "[null, {\"field\": 1}]" :: BS.ByteString
+  let ibip    = JCF.simdToIbBp jsonBs
+  let cursor  = JCF.fromBsIbBp jsonBs ibip
+  let _ = fc cursor
+  let _ = (fc >=> ns) cursor
+  return ()
diff --git a/examples/Example4.hs b/examples/Example4.hs
new file mode 100644
--- /dev/null
+++ b/examples/Example4.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE BangPatterns      #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-matches     #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing     #-}
+{-# OPTIONS_GHC -fno-warn-unused-local-binds #-}
+
+module Example4 where
+
+import Control.Monad
+import Data.Function
+import Data.List
+import HaskellWorks.Data.Json.PartialValue
+import HaskellWorks.Data.Json.Standard.Cursor.Load.Cursor
+import HaskellWorks.Data.Json.Standard.Load.Partial
+import HaskellWorks.Data.MQuery
+import HaskellWorks.Data.MQuery.Micro
+
+import qualified Data.DList as DL
+
+{- HLINT ignore "Reduce duplication" -}
+
+example :: IO ()
+example = do
+  !cursor <- loadPartial "corpus/bench/78mb.json"
+  !cursor <- loadCursorWithIndex "corpus/bench/78mb.json"
+  !cursor <- loadCursor "corpus/bench/78mb.json"
+  !cursor <- loadCursorWithCsPoppyIndex "corpus/bench/78mb.json"
+  let !json = jsonPartialJsonValueAt cursor
+  let q = MQuery (DL.singleton json)
+
+  putPretty $ q >>= item & limit 10
+  putPretty $ q >>= item & page 10 1
+  putPretty $ q >>= item >>= hasKV "founded_year" (JsonPartialNumber 2005) & limit 10
+  putPretty $ q >>= item >>= entry
+  putPretty $ q >>= item >>= entry >>= named "name" & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> entry >=> named "price_currency_code")
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> entry >=> named "price_currency_code") & onList (uniq . sort)
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> having (entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") >=> entry >=> named "price_amount") & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> having (entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") >=> entry >=> named "price_amount" >=> castAsInteger ) & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> having (entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") >=> entry >=> named "price_amount" >=> castAsInteger ) & aggregate sum
+
+  putPretty $ q >>= item & limit 10
+  putPretty $ q >>= item & page 10 1
+  putPretty $ q >>= item >>= entry
+  putPretty $ q >>= item >>= entry >>= named "name" & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> entry >=> named "price_currency_code" >=> asString)
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> entry >=> named "price_currency_code" >=> asString) & onList (uniq . sort)
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> having (entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") >=> entry >=> named "price_amount") & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> having (entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") >=> entry >=> named "price_amount" >=> castAsInteger ) & limit 10
+  putPretty $ q >>= (item >=> entry >=> named "acquisition" >=> having (entry >=> named "price_currency_code" >=> asString >=> valueOf "USD") >=> entry >=> named "price_amount" >=> castAsInteger ) & aggregate sum
+
+  return ()
diff --git a/hw-json.cabal b/hw-json.cabal
--- a/hw-json.cabal
+++ b/hw-json.cabal
@@ -1,222 +1,248 @@
 cabal-version:  2.2
 
-name:           hw-json
-version:        1.0.0.2
-synopsis:       Memory efficient JSON parser
-description:    Memory efficient JSON parser. Please see README.md
-category:       Data
-homepage:       http://github.com/haskell-works/hw-json#readme
-bug-reports:    https://github.com/haskell-works/hw-json/issues
-author:         John Ky
-maintainer:     newhoggy@gmail.com
-copyright:      2016 - 2019 John Ky
-license:        BSD-3-Clause
-license-file:   LICENSE
-build-type:     Simple
-extra-source-files:
-    README.md
-    corpus/5000B.json
-    corpus/5000B.json.bp.idx
-    corpus/5000B.json.ib.idx
-    corpus/issue-0001.json
-    corpus/issue-0001.json.bp.idx
-    corpus/issue-0001.json.ib.idx
-    corpus/issue-0001.md
+name:                   hw-json
+version:                1.3.3.1
+synopsis:               Memory efficient JSON parser
+description:            Memory efficient JSON parser. Please see README.md
+category:               Data
+homepage:               http://github.com/haskell-works/hw-json#readme
+bug-reports:            https://github.com/haskell-works/hw-json/issues
+author:                 John Ky
+maintainer:             newhoggy@gmail.com
+copyright:              2016-2025 John Ky
+license:                BSD-3-Clause
+license-file:           LICENSE
+tested-with:            GHC == 9.12.2, GHC == 9.10.2, GHC == 9.8.4, GHC == 9.6.7
+build-type:             Simple
+extra-source-files:     README.md
+                        corpus/5000B.json
+                        corpus/5000B.json.bp.idx
+                        corpus/5000B.json.ib.idx
+                        corpus/issue-0001.json
+                        corpus/issue-0001.json.bp.idx
+                        corpus/issue-0001.json.ib.idx
+                        corpus/issue-0001.md
 
 source-repository head
   type: git
   location: https://github.com/haskell-works/hw-json
 
 flag bmi2
-  description: Enable bmi2 instruction set
-  manual: False
-  default: False
+  description:  Enable bmi2 instruction set
+  manual:       False
+  default:      False
 
 flag sse42
-  description: Enable sse4.2 instruction set
-  manual: False
-  default: False
-
-common base                 { build-depends: base                 >= 4          && < 5      }
+  description:  Enable sse4.2 instruction set
+  manual:       False
+  default:      False
 
-common ansi-wl-pprint       { build-depends: ansi-wl-pprint       >= 0.6.8.2    && < 0.7    }
-common array                { build-depends: array                >= 0.5        && < 0.6    }
-common attoparsec           { build-depends: attoparsec           >= 0.13       && < 0.14   }
-common bits-extra           { build-depends: bits-extra           >= 0.0.1      && < 0.1    }
-common bytestring           { build-depends: bytestring           >= 0.10.6     && < 0.11   }
-common criterion            { build-depends: criterion            >= 1.4        && < 1.6    }
-common directory            { build-depends: directory            >= 1.3        && < 1.4    }
-common dlist                { build-depends: dlist                >= 0.8        && < 0.9    }
-common generic-lens         { build-depends: generic-lens         >= 1.1.0.0    && < 1.2    }
-common hedgehog             { build-depends: hedgehog             >= 0.5        && < 0.7    }
-common hspec                { build-depends: hspec                >= 2.4        && < 3      }
-common hw-balancedparens    { build-depends: hw-balancedparens    >= 0.2.0.1    && < 0.3    }
-common hw-bits              { build-depends: hw-bits              >= 0.7.0.5    && < 0.8    }
-common hw-hspec-hedgehog    { build-depends: hw-hspec-hedgehog    >= 0.1.0.4    && < 0.2    }
-common hw-json-simd         { build-depends: hw-json-simd         >= 0.1.0.2    && < 0.2    }
-common hw-mquery            { build-depends: hw-mquery            >= 0.2.0.0    && < 0.3    }
-common hw-parser            { build-depends: hw-parser            >= 0.1        && < 0.2    }
-common hw-prim              { build-depends: hw-prim              >= 0.6.2.21   && < 0.7    }
-common hw-rankselect        { build-depends: hw-rankselect        >= 0.13       && < 0.14   }
-common hw-rankselect-base   { build-depends: hw-rankselect-base   >= 0.3.2.1    && < 0.4    }
-common hw-simd              { build-depends: hw-simd              >= 0.1.1.2    && < 0.2    }
-common lens                 { build-depends: lens                 >= 4          && < 5      }
-common mmap                 { build-depends: mmap                 >= 0.5        && < 0.6    }
-common optparse-applicative { build-depends: optparse-applicative >= 0.14       && < 0.15   }
-common text                 { build-depends: text                 >= 1.2        && < 1.3    }
-common transformers         { build-depends: transformers         >= 0.4        && < 0.6    }
-common vector               { build-depends: vector               >= 0.12       && < 0.13   }
-common word8                { build-depends: word8                >= 0.1        && < 0.2    }
+common base                       { build-depends: base                       >= 4.11       && < 5      }
 
-common semigroups   { if impl(ghc <  8    ) { build-depends: semigroups     >= 0.16     && < 0.19 } }
+common aeson                      { build-depends: aeson                      >= 2.0        && < 2.3    }
+common array                      { build-depends: array                      >= 0.5        && < 0.6    }
+common attoparsec                 { build-depends: attoparsec                 >= 0.13       && < 0.15   }
+common attoparsec-aeson           { build-depends: attoparsec-aeson           >= 2          && < 3      }
+common bits-extra                 { build-depends: bits-extra                 >= 0.0.1.3    && < 0.1    }
+common bytestring                 { build-depends: bytestring                 >= 0.10.6     && < 0.13   }
+common criterion                  { build-depends: criterion                  >= 1.4        && < 1.7    }
+common directory                  { build-depends: directory                  >= 1.3        && < 1.4    }
+common dlist                      { build-depends: dlist                      >= 0.8        && < 1.1    }
+common doctest                    { build-depends: doctest                    >= 0.16.2     && < 1      }
+common doctest-discover           { build-depends: doctest-discover           >= 0.2        && < 0.3    }
+common generic-lens               { build-depends: generic-lens               >= 1.2.0.1    && < 2.3    }
+common hedgehog                   { build-depends: hedgehog                   >= 0.6        && < 2      }
+common hspec                      { build-depends: hspec                      >= 2.4        && < 3      }
+common hw-balancedparens          { build-depends: hw-balancedparens          >= 0.3.0.0    && < 0.5    }
+common hw-bits                    { build-depends: hw-bits                    >= 0.7.0.5    && < 0.8    }
+common hw-hspec-hedgehog          { build-depends: hw-hspec-hedgehog          >= 0.1.0.4    && < 0.2    }
+common hw-json-simd {
+  if arch(x86_64)
+    build-depends: hw-json-simd               >= 0.1.0.2    && < 0.2
+}
+common hw-json-simple-cursor      { build-depends: hw-json-simple-cursor      >= 0.1.0.1    && < 0.2    }
+common hw-json-standard-cursor    { build-depends: hw-json-standard-cursor    >= 0.2.0.1    && < 0.3    }
+common hw-mquery                  { build-depends: hw-mquery                  >= 0.2.0.0    && < 0.3    }
+common hw-parser                  { build-depends: hw-parser                  >= 0.1        && < 0.2    }
+common hw-prim                    { build-depends: hw-prim                    >= 0.6.2.32   && < 0.7    }
+common hw-rankselect              { build-depends: hw-rankselect              >= 0.13       && < 0.14   }
+common hw-rankselect-base         { build-depends: hw-rankselect-base         >= 0.3.2.1    && < 0.4    }
+common hw-simd {
+  if arch(x86_64)
+    build-depends: hw-simd                    >= 0.1.1.2    && < 0.2
+}
+common lens                       { build-depends: lens                       >= 4          && < 6      }
+common mmap                       { build-depends: mmap                       >= 0.5        && < 0.6    }
+common optparse-applicative       { build-depends: optparse-applicative       >= 0.14       && < 0.19   }
+common prettyprinter              { build-depends: prettyprinter              >= 1          && < 2      }
+common scientific                 { build-depends: scientific                 >= 0.3.6.2    && < 0.4    }
+common text                       { build-depends: text                       >= 1.2        && < 3      }
+common transformers               { build-depends: transformers               >= 0.4        && < 0.7    }
+common unordered-containers       { build-depends: unordered-containers       >= 0.2        && < 0.3    }
+common vector                     { build-depends: vector                     >= 0.12       && < 0.14   }
+common word8                      { build-depends: word8                      >= 0.1        && < 0.2    }
 
 common config
-  default-language: Haskell2010
-  ghc-options: -Wall
+  default-language:     Haskell2010
+  ghc-options:          -Wall -O2 -msse4.2
   if flag(sse42)
-    ghc-options: -mbmi2
+    ghc-options:        -msse4.2
   if flag(bmi2) && impl(ghc >= 8.4.1)
-    ghc-options: -mbmi2 -msse4.2
-    cpp-options: -DBMI2_ENABLED
+    ghc-options:        -mbmi2 -msse4.2
+    cpp-options:        -DBMI2_ENABLED
 
+common hw-json
+  build-depends:        hw-json
+
 library
-  import:   base, config
-          , ansi-wl-pprint
-          , array
-          , attoparsec
-          , bits-extra
-          , bytestring
-          , dlist
-          , hw-balancedparens
-          , hw-bits
-          , hw-mquery
-          , hw-parser
-          , hw-prim
-          , hw-rankselect
-          , hw-rankselect-base
-          , hw-simd
-          , mmap
-          , semigroups
-          , text
-          , vector
-          , word8
-  hs-source-dirs:   src
-  ghc-options:      -O2 -msse4.2
-  other-modules:    Paths_hw_json
-  autogen-modules:  Paths_hw_json
-  exposed-modules:
-      HaskellWorks.Data.Json
-      HaskellWorks.Data.Json.Backend.Simple.Cursor
-      HaskellWorks.Data.Json.Backend.Simple.Fast
-      HaskellWorks.Data.Json.Backend.Simple.SemiIndex
-      HaskellWorks.Data.Json.Backend.Simple.Value
-      HaskellWorks.Data.Json.Backend.Standard.Cursor
-      HaskellWorks.Data.Json.Backend.Standard.Fast
-      HaskellWorks.Data.Json.Backend.Standard.Index
-      HaskellWorks.Data.Json.Backend.Standard.Load.Cursor
-      HaskellWorks.Data.Json.Backend.Standard.Load.Partial
-      HaskellWorks.Data.Json.Backend.Standard.Load.Raw
-      HaskellWorks.Data.Json.Backend.Standard.SemiIndex
-      HaskellWorks.Data.Json.Backend.Standard.Slow
-      HaskellWorks.Data.Json.DecodeError
-      HaskellWorks.Data.Json.FromValue
-      HaskellWorks.Data.Json.Internal.Backend.Standard.Blank
-      HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson
-      HaskellWorks.Data.Json.Internal.Backend.Standard.Cursor.Token
-      HaskellWorks.Data.Json.Internal.Backend.Standard.IbBp
-      HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex
-      HaskellWorks.Data.Json.Internal.Backend.Standard.StateMachine
-      HaskellWorks.Data.Json.Internal.Backend.Standard.ToBalancedParens64
-      HaskellWorks.Data.Json.Internal.Backend.Standard.ToInterestBits64
-      HaskellWorks.Data.Json.Internal.Backend.Standard.Token.Tokenize
-      HaskellWorks.Data.Json.Internal.Backend.Simple.IbBp
-      HaskellWorks.Data.Json.Internal.Backend.Simple.ToIbBp
-      HaskellWorks.Data.Json.Internal.CharLike
-      HaskellWorks.Data.Json.Internal.Doc
-      HaskellWorks.Data.Json.Internal.Index
-      HaskellWorks.Data.Json.Internal.PartialIndex
-      HaskellWorks.Data.Json.Internal.Slurp
-      HaskellWorks.Data.Json.Internal.Token
-      HaskellWorks.Data.Json.Internal.Token.Types
-      HaskellWorks.Data.Json.Internal.Value
-      HaskellWorks.Data.Json.Internal.Word64
-      HaskellWorks.Data.Json.Internal.Word8
-      HaskellWorks.Data.Json.LightJson
-      HaskellWorks.Data.Json.PartialValue
-      HaskellWorks.Data.Json.Query
-      HaskellWorks.Data.Json.Type
-      HaskellWorks.Data.Json.Value
+  import:               base, config
+                      , aeson
+                      , attoparsec
+                      , attoparsec-aeson
+                      , bits-extra
+                      , bytestring
+                      , dlist
+                      , hw-balancedparens
+                      , hw-bits
+                      , hw-json-simple-cursor
+                      , hw-json-standard-cursor
+                      , hw-mquery
+                      , hw-parser
+                      , hw-prim
+                      , hw-rankselect
+                      , hw-rankselect-base
+                      , hw-simd
+                      , mmap
+                      , prettyprinter
+                      , scientific
+                      , text
+                      , vector
+                      , word8
+  hs-source-dirs:       src
+  other-modules:        Paths_hw_json
+  autogen-modules:      Paths_hw_json
+  exposed-modules:      HaskellWorks.Data.Json.DecodeError
+                        HaskellWorks.Data.Json.FromValue
+                        HaskellWorks.Data.Json.Internal.CharLike
+                        HaskellWorks.Data.Json.Internal.Doc
+                        HaskellWorks.Data.Json.Internal.Index
+                        HaskellWorks.Data.Json.Internal.PartialIndex
+                        HaskellWorks.Data.Json.Internal.Slurp
+                        HaskellWorks.Data.Json.Internal.Standard.Cursor.Token
+                        HaskellWorks.Data.Json.Internal.Standard.Token.Tokenize
+                        HaskellWorks.Data.Json.Internal.Token
+                        HaskellWorks.Data.Json.Internal.Token.Types
+                        HaskellWorks.Data.Json.Internal.Value
+                        HaskellWorks.Data.Json.Internal.Word64
+                        HaskellWorks.Data.Json.LightJson
+                        HaskellWorks.Data.Json.PartialValue
+                        HaskellWorks.Data.Json.Query
+                        HaskellWorks.Data.Json.Simple.Value
+                        HaskellWorks.Data.Json.Standard.Load.Partial
+                        HaskellWorks.Data.Json.Value
 
 executable hw-json
-  import:   base, config
-          , bytestring
-          , dlist
-          , generic-lens
-          , hw-balancedparens
-          , hw-json-simd
-          , hw-mquery
-          , hw-prim
-          , hw-rankselect
-          , hw-rankselect-base
-          , lens
-          , mmap
-          , optparse-applicative
-          , semigroups
-          , vector
-  main-is:        Main.hs
-  hs-source-dirs: app
-  ghc-options:    -threaded -rtsopts -with-rtsopts=-N -O2 -msse4.2
-  build-depends:  hw-json
-  other-modules:
-      App.Commands
-      App.Commands.CreateIndex
-      App.Commands.Demo
-      App.Commands.Types
+  import:               base, config
+                      , aeson
+                      , bytestring
+                      , dlist
+                      , generic-lens
+                      , hw-balancedparens
+                      , hw-json
+                      , hw-json-simd
+                      , hw-json-simple-cursor
+                      , hw-json-standard-cursor
+                      , hw-mquery
+                      , hw-prim
+                      , hw-rankselect
+                      , hw-rankselect-base
+                      , lens
+                      , mmap
+                      , optparse-applicative
+                      , text
+                      , unordered-containers
+                      , vector
+  main-is:              Main.hs
+  hs-source-dirs:       app
+  ghc-options:          -threaded -rtsopts -with-rtsopts=-N
+  other-modules:        App.Commands
+                        App.Commands.CreateIndex
+                        App.Commands.Count
+                        App.Commands.CountAeson
+                        App.Commands.Demo
+                        App.Commands.Types
 
 test-suite hw-json-test
-  import:   base, config
-          , attoparsec
-          , bytestring
-          , hedgehog
-          , hspec
-          , hw-balancedparens
-          , hw-bits
-          , hw-hspec-hedgehog
-          , hw-prim
-          , hw-rankselect
-          , hw-rankselect-base
-          , transformers
-          , vector
-  type:           exitcode-stdio-1.0
-  main-is:        Spec.hs
-  build-depends:  hw-json
-  hs-source-dirs: test
-  ghc-options:    -threaded -rtsopts -with-rtsopts=-N
-  build-tools:    hspec-discover
-  other-modules:
-      HaskellWorks.Data.Json.Backend.Simple.CursorSpec
-      HaskellWorks.Data.Json.Backend.Standard.Succinct.Cursor.BalancedParensSpec
-      HaskellWorks.Data.Json.Backend.Standard.Succinct.Cursor.InterestBitsSpec
-      HaskellWorks.Data.Json.Backend.Standard.Succinct.CursorSpec
-      HaskellWorks.Data.Json.Backend.Standard.Succinct.GenCursorTest
-      HaskellWorks.Data.Json.CorpusSpec
-      HaskellWorks.Data.Json.Internal.BlankSpec
-      HaskellWorks.Data.Json.Succinct.Cursor.BalancedParensSpec
-      HaskellWorks.Data.Json.Token.TokenizeSpec
-      HaskellWorks.Data.Json.TypeSpec
-      HaskellWorks.Data.Json.ValueSpec
-      Paths_hw_json
+  import:               base, config
+                      , aeson
+                      , attoparsec
+                      , attoparsec-aeson
+                      , bytestring
+                      , dlist
+                      , hedgehog
+                      , hspec
+                      , hw-balancedparens
+                      , hw-bits
+                      , hw-hspec-hedgehog
+                      , hw-json
+                      , hw-json-simple-cursor
+                      , hw-json-standard-cursor
+                      , hw-mquery
+                      , hw-prim
+                      , hw-rankselect
+                      , hw-rankselect-base
+                      , scientific
+                      , text
+                      , transformers
+                      , vector
+  type:                 exitcode-stdio-1.0
+  main-is:              Spec.hs
+  hs-source-dirs:       test
+  ghc-options:          -threaded -rtsopts -with-rtsopts=-N
+  build-tool-depends:   hspec-discover:hspec-discover
+  other-modules:        HaskellWorks.Data.Json.LightJsonSpec
+                        HaskellWorks.Data.Json.Simple.CursorSpec
+                        HaskellWorks.Data.Json.Standard.CursorSpec
+                        HaskellWorks.Data.Json.Standard.GenCursorTest
+                        HaskellWorks.Data.Json.Token.TokenizeSpec
+                        HaskellWorks.Data.Json.TypeSpec
+                        HaskellWorks.Data.Json.ValueSpec
 
+library examples
+  import:               base, config
+                      , aeson
+                      , bytestring
+                      , dlist
+                      , hw-json
+                      , hw-json-standard-cursor
+                      , hw-mquery
+                      , hw-prim
+  hs-source-dirs:       examples
+  other-modules:        Example1
+                        Example2
+                        Example3
+                        Example4
+
 benchmark bench
-  import:   base, config
-          , bytestring
-          , criterion
-          , directory
-          , mmap
-          , semigroups
-  type:           exitcode-stdio-1.0
-  main-is:        Main.hs
-  hs-source-dirs: bench
-  ghc-options:    -O2 -msse4.2
-  build-depends:  hw-json
-  other-modules:  Paths_hw_json
+  import:               base, config
+                      , bytestring
+                      , criterion
+                      , directory
+                      , hw-json
+                      , hw-json-standard-cursor
+                      , mmap
+  type:                 exitcode-stdio-1.0
+  main-is:              Main.hs
+  hs-source-dirs:       bench
+
+test-suite doctest
+  import:               base, config
+                      , doctest
+                      , doctest-discover
+                      , hw-json
+  default-language:     Haskell2010
+  type:                 exitcode-stdio-1.0
+  ghc-options:          -threaded -rtsopts -with-rtsopts=-N
+  main-is:              DoctestDriver.hs
+  HS-Source-Dirs:       doctest
+  build-tool-depends:   doctest-discover:doctest-discover
diff --git a/src/HaskellWorks/Data/Json.hs b/src/HaskellWorks/Data/Json.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json.hs
+++ /dev/null
@@ -1,11 +0,0 @@
--- |
--- Copyright: 2016 John Ky
--- License: MIT
---
--- Json
-module HaskellWorks.Data.Json
-    ( module X
-    ) where
-
-import HaskellWorks.Data.Json.Type  as X
-import HaskellWorks.Data.Json.Value as X
diff --git a/src/HaskellWorks/Data/Json/Backend/Simple/Cursor.hs b/src/HaskellWorks/Data/Json/Backend/Simple/Cursor.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Simple/Cursor.hs
+++ /dev/null
@@ -1,89 +0,0 @@
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-
-module HaskellWorks.Data.Json.Backend.Simple.Cursor
-  ( JsonCursor(..)
-  , jsonCursorPos
-  ) where
-
-import Data.String
-import Data.Word
-import HaskellWorks.Data.FromByteString
-import HaskellWorks.Data.FromForeignRegion
-import HaskellWorks.Data.Positioning
-import HaskellWorks.Data.RankSelect.Base.Rank0
-import HaskellWorks.Data.RankSelect.Base.Rank1
-import HaskellWorks.Data.RankSelect.Base.Select1
-import HaskellWorks.Data.RankSelect.Poppy512
-import HaskellWorks.Data.TreeCursor
-import Prelude                                   hiding (drop)
-
-import qualified Data.ByteString                                 as BS
-import qualified Data.ByteString.Char8                           as BSC
-import qualified Data.ByteString.Internal                        as BSI
-import qualified Data.Vector.Storable                            as DVS
-import qualified Foreign.ForeignPtr                              as F
-import qualified HaskellWorks.Data.BalancedParens                as BP
-import qualified HaskellWorks.Data.Json.Backend.Simple.SemiIndex as SI
-
-data JsonCursor t v w = JsonCursor
-  { cursorText     :: !t
-  , interests      :: !v
-  , balancedParens :: !w
-  , cursorRank     :: !Count
-  }
-  deriving (Eq, Show)
-
-instance FromByteString (JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))) where
-  fromByteString bs = JsonCursor
-    { cursorText      = bs
-    , interests       = ib
-    , balancedParens  = BP.SimpleBalancedParens bp
-    , cursorRank      = 1
-    }
-    where SI.SemiIndex _ ib bp = SI.buildSemiIndex bs
-
-instance FromByteString (JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))) where
-  fromByteString bs = JsonCursor
-    { cursorText      = bs
-    , interests       = makePoppy512 ib
-    , balancedParens  = BP.SimpleBalancedParens bp
-    , cursorRank      = 1
-    }
-    where SI.SemiIndex _ ib bp = SI.buildSemiIndex bs
-
-instance FromForeignRegion (JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))) where
-  fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (F.castForeignPtr fptr) offset size)
-
-instance FromForeignRegion (JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))) where
-  fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (F.castForeignPtr fptr) offset size)
-
-instance IsString (JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))) where
-  fromString = fromByteString . BSC.pack
-
-instance IsString (JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))) where
-  fromString = fromByteString . BSC.pack
-
-instance (BP.BalancedParens u, Rank1 u, Rank0 u) => TreeCursor (JsonCursor t v u) where
-  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 -> Maybe (JsonCursor t v u)
-  nextSibling k = (\q -> k { cursorRank = q }) <$> BP.nextSibling (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 -> Maybe Count
-  depth k = BP.depth (balancedParens k) (cursorRank k)
-
-  subtreeSize :: JsonCursor t v u -> Maybe Count
-  subtreeSize k = BP.subtreeSize (balancedParens k) (cursorRank k)
-
-jsonCursorPos :: (Rank1 w, Select1 v) => JsonCursor s v w -> Position
-jsonCursorPos k = toPosition (select1 ik (rank1 bpk (cursorRank k)) - 1)
-  where ik  = interests k
-        bpk = balancedParens k
diff --git a/src/HaskellWorks/Data/Json/Backend/Simple/Fast.hs b/src/HaskellWorks/Data/Json/Backend/Simple/Fast.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Simple/Fast.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module HaskellWorks.Data.Json.Backend.Simple.Fast
-  ( makeCursor
-  ) where
-
-import Data.Word
-import Foreign.ForeignPtr
-import HaskellWorks.Data.FromForeignRegion
-import HaskellWorks.Data.Json.Backend.Simple.Cursor
-import HaskellWorks.Data.RankSelect.Poppy512
-
-import qualified Data.ByteString                                       as BS
-import qualified Data.ByteString.Char8                                 as BSC
-import qualified Data.ByteString.Internal                              as BSI
-import qualified Data.Vector.Storable                                  as DVS
-import qualified HaskellWorks.Data.BalancedParens                      as BP
-import qualified HaskellWorks.Data.Json.Internal.Backend.Simple.IbBp   as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Simple.ToIbBp as J
-
-class MakeCursor a where
-  makeCursor :: a -> JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))
-
-instance MakeCursor BS.ByteString where
-  makeCursor bs = JsonCursor
-    { cursorText      = bs
-    , interests       = makePoppy512 ib
-    , balancedParens  = BP.SimpleBalancedParens bp
-    , cursorRank      = 1
-    }
-    where J.IbBp ib bp = J.toIbBp bs
-
-instance MakeCursor String where
-  makeCursor = makeCursor . BSC.pack
-
-instance MakeCursor ForeignRegion where
-  makeCursor (fptr, offset, size) = makeCursor (BSI.fromForeignPtr (castForeignPtr fptr) offset size)
diff --git a/src/HaskellWorks/Data/Json/Backend/Simple/SemiIndex.hs b/src/HaskellWorks/Data/Json/Backend/Simple/SemiIndex.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Simple/SemiIndex.hs
+++ /dev/null
@@ -1,80 +0,0 @@
-{-# LANGUAGE DeriveFunctor     #-}
-{-# LANGUAGE DeriveTraversable #-}
-{-# LANGUAGE InstanceSigs      #-}
-{-# LANGUAGE MultiWayIf        #-}
-
-module HaskellWorks.Data.Json.Backend.Simple.SemiIndex
-  ( buildSemiIndex
-  , SemiIndex(..)
-  ) where
-
-import Control.Monad.ST
-import Data.Word
-
-import qualified Data.ByteString                        as BS
-import qualified Data.ByteString.Unsafe                 as BSU
-import qualified Data.Vector.Storable                   as DVS
-import qualified HaskellWorks.Data.Bits.Writer.Storable as W
-import qualified HaskellWorks.Data.Json.Internal.Word8  as W8
-
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-
-data Context = InJson | InString | InEscape deriving (Eq, Show)
-
-data SemiIndex v = SemiIndex
-  { semiIndexContext :: !Context
-  , semiIndexIb      :: !v
-  , semiIndexBp      :: !v
-  } deriving (Functor, Traversable, Foldable)
-
-buildSemiIndex :: BS.ByteString -> SemiIndex (DVS.Vector Word64)
-buildSemiIndex bs = DVS.createT $ do
-  let len = (BS.length bs + 7) `div` 8
-  mib <- W.newWriter len
-  mbp <- W.newWriter (len * 2)
-  buildFromByteString mib mbp bs 0 InJson
-{-# INLINE buildSemiIndex #-}
-
-buildFromByteString :: W.Writer s -> W.Writer s -> BS.ByteString -> Int -> Context -> ST s (SemiIndex (DVS.MVector s Word64))
-buildFromByteString ib bp bs i context = if i < BS.length bs
-  then do
-    let c = BSU.unsafeIndex bs i
-    case context of
-      InJson -> if
-        | c == W8.openBracket || c == W8.openBrace -> do
-          W.unsafeWriteBit bp 1
-          W.unsafeWriteBit bp 1
-          W.unsafeWriteBit ib 1
-          buildFromByteString ib bp bs (i + 1) InJson
-        | c == W8.closeBracket || c == W8.closeBrace -> do
-          W.unsafeWriteBit bp 0
-          W.unsafeWriteBit bp 0
-          W.unsafeWriteBit ib 1
-          buildFromByteString ib bp bs (i + 1) InJson
-        | c == W8.comma || c == W8.colon -> do
-          W.unsafeWriteBit bp 0
-          W.unsafeWriteBit bp 1
-          W.unsafeWriteBit ib 1
-          buildFromByteString ib bp bs (i + 1) InJson
-        | c == W8.doubleQuote -> do
-          W.unsafeWriteBit ib 0
-          buildFromByteString ib bp bs (i + 1) InString
-        | otherwise -> do
-          W.unsafeWriteBit ib 0
-          buildFromByteString ib bp bs (i + 1) InJson
-      InString -> do
-        W.unsafeWriteBit ib 0
-        let newContext = if
-              | c == W8.doubleQuote  -> InJson
-              | c == W8.backSlash    -> InEscape
-              | otherwise           -> InString
-        buildFromByteString ib bp bs (i + 1) newContext
-      InEscape -> do
-        W.unsafeWriteBit ib 0
-        buildFromByteString ib bp bs (i + 1) InString
-  else do
-    ibv <- W.written ib
-    bpv <- W.written bp
-    return (SemiIndex context ibv bpv)
-{-# INLINE buildFromByteString #-}
diff --git a/src/HaskellWorks/Data/Json/Backend/Simple/Value.hs b/src/HaskellWorks/Data/Json/Backend/Simple/Value.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Simple/Value.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-module HaskellWorks.Data.Json.Backend.Simple.Value where
-
-import Data.Maybe
-import Data.Word
-import HaskellWorks.Data.Json.Backend.Simple.Cursor
-import HaskellWorks.Data.Positioning
-import HaskellWorks.Data.RankSelect.Base.Select1
-import HaskellWorks.Data.RankSelect.Poppy512
-
-import qualified Data.ByteString                  as BS
-import qualified Data.Vector.Storable             as DVS
-import qualified HaskellWorks.Data.BalancedParens as BP
-
-data JsonValue
-  = JsonValues JsonValues
-  | JsonNull
-  | JsonNumber Double
-  | JsonString String
-  | JsonBoolean Bool
-  deriving (Eq, Show)
-
-data JsonValues
-  = JsonArray  [JsonValue]
-  | JsonObject [(String, JsonValue)]
-  deriving (Eq, Show)
-
-snippetPos :: JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64)) -> (Count, Count)
-snippetPos k = (kpa, kpz)
-  where kpa   = select1 kib kta + km
-        kpz   = select1 kib ktz - km
-        kib   = interests k
-        kbp   = balancedParens k
-        kra   = cursorRank k
-        krz   = fromMaybe maxBound (BP.findClose kbp kra)
-        ksa   = kra + 1
-        ksz   = krz + 1
-        kta   = ksa `div` 2
-        ktz   = ksz `div` 2
-        km    = ksa `mod` 2
-
-snippet :: JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64)) -> BS.ByteString
-snippet k = let (a, z) = snippetPos k in BS.take (fromIntegral (z - a + 1)) (BS.drop (fromIntegral (a - 1)) kt)
-  where kt    = cursorText k
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Cursor.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Cursor.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Cursor.hs
+++ /dev/null
@@ -1,173 +0,0 @@
-{-# LANGUAGE BangPatterns          #-}
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Cursor
-  ( JsonCursor(..)
-  , jsonCursorPos
-  ) where
-
-import Control.Arrow
-import Control.Monad
-import Data.Char
-import Data.String
-import Data.Word8
-import HaskellWorks.Data.Bits.BitWise
-import HaskellWorks.Data.Drop
-import HaskellWorks.Data.Json.DecodeError
-import HaskellWorks.Data.Json.Internal.CharLike
-import HaskellWorks.Data.Json.Internal.Index
-import HaskellWorks.Data.Json.Internal.PartialIndex
-import HaskellWorks.Data.Json.Internal.Slurp
-import HaskellWorks.Data.Json.Internal.Word8
-import HaskellWorks.Data.Json.LightJson
-import HaskellWorks.Data.Json.PartialValue
-import HaskellWorks.Data.Json.Type
-import HaskellWorks.Data.Positioning
-import HaskellWorks.Data.RankSelect.Base.Rank0
-import HaskellWorks.Data.RankSelect.Base.Rank1
-import HaskellWorks.Data.RankSelect.Base.Select1
-import HaskellWorks.Data.TreeCursor
-import HaskellWorks.Data.Uncons
-import Prelude                                      hiding (drop)
-
-import qualified Data.ByteString                  as BS
-import qualified Data.List                        as L
-import qualified HaskellWorks.Data.BalancedParens as BP
-
-data JsonCursor t v w = JsonCursor
-  { cursorText     :: !t
-  , interests      :: !v
-  , balancedParens :: !w
-  , cursorRank     :: !Count
-  }
-  deriving (Eq, Show)
-
-instance (BP.BalancedParens u, Rank1 u, Rank0 u) => TreeCursor (JsonCursor t v u) where
-  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 -> Maybe (JsonCursor t v u)
-  nextSibling k = (\q -> k { cursorRank = q }) <$> BP.nextSibling (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 -> Maybe Count
-  depth k = BP.depth (balancedParens k) (cursorRank k)
-
-  subtreeSize :: JsonCursor t v u -> Maybe Count
-  subtreeSize k = BP.subtreeSize (balancedParens k) (cursorRank k)
-
-jsonCursorPos :: (Rank1 w, Select1 v) => JsonCursor s v w -> Position
-jsonCursorPos k = toPosition (select1 ik (rank1 bpk (cursorRank k)) - 1)
-  where ik  = interests k
-        bpk = balancedParens k
-
-instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => LightJsonAt (JsonCursor BS.ByteString v w) where
-  lightJsonAt k = case uncons remainder of
-    Just (!c, _) | isLeadingDigit2 c -> LightJsonNumber  (slurpNumber remainder)
-    Just (!c, _) | isQuotDbl c       -> LightJsonString  (slurpString remainder)
-    Just (!c, _) | isChar_t c        -> LightJsonBool    True
-    Just (!c, _) | isChar_f c        -> LightJsonBool    False
-    Just (!c, _) | isChar_n c        -> LightJsonNull
-    Just (!c, _) | isBraceLeft c     -> LightJsonObject (mapValuesFrom   (firstChild k))
-    Just (!c, _) | isBracketLeft c   -> LightJsonArray  (arrayValuesFrom (firstChild k))
-    Just _                           -> LightJsonError "Invalid Json Type"
-    Nothing                          -> LightJsonError "End of data"
-    where ik                = interests k
-          bpk               = balancedParens k
-          p                 = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
-          remainder         = drop (toCount p) (cursorText k)
-          arrayValuesFrom   = L.unfoldr (fmap (id &&& nextSibling))
-          mapValuesFrom j   = pairwise (arrayValuesFrom j) >>= asField
-          pairwise (a:b:rs) = (a, b) : pairwise rs
-          pairwise _        = []
-          asField (a, b)    = case lightJsonAt a of
-                                LightJsonString s -> [(s, b)]
-                                _                 -> []
-
-instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonTypeAt (JsonCursor String v w) where
-  jsonTypeAtPosition p k = case drop (toCount p) (cursorText k) of
-    c:_ | fromIntegral (ord c) == _bracketleft      -> Just JsonTypeArray
-    c:_ | fromIntegral (ord c) == _f                -> Just JsonTypeBool
-    c:_ | fromIntegral (ord c) == _t                -> Just JsonTypeBool
-    c:_ | fromIntegral (ord c) == _n                -> Just JsonTypeNull
-    c:_ | wIsJsonNumberDigit (fromIntegral (ord c)) -> Just JsonTypeNumber
-    c:_ | fromIntegral (ord c) == _braceleft        -> Just JsonTypeObject
-    c:_ | fromIntegral (ord c) == _quotedbl         -> Just JsonTypeString
-    _                                               -> Nothing
-
-  jsonTypeAt k = jsonTypeAtPosition p k
-    where p   = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
-          ik  = interests k
-          bpk = balancedParens k
-
-instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonTypeAt (JsonCursor BS.ByteString v w) where
-  jsonTypeAtPosition p k = case BS.uncons (drop (toCount p) (cursorText k)) of
-    Just (c, _) | c == _bracketleft    -> Just JsonTypeArray
-    Just (c, _) | c == _f              -> Just JsonTypeBool
-    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
-
-  jsonTypeAt k = jsonTypeAtPosition p k
-    where p   = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
-          ik  = interests k
-          bpk = balancedParens k
-
-instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonPartialIndexAt (JsonCursor BS.ByteString v w) where
-  jsonPartialIndexAt k = case uncons remainder of
-    Just (!c, _) | isLeadingDigit2 c -> JsonPartialIndexNumber  remainder
-    Just (!c, _) | isQuotDbl c       -> JsonPartialIndexString  remainder
-    Just (!c, _) | isChar_t c        -> JsonPartialIndexBool    True
-    Just (!c, _) | isChar_f c        -> JsonPartialIndexBool    False
-    Just (!c, _) | isChar_n c        -> JsonPartialIndexNull
-    Just (!c, _) | isBraceLeft c     -> JsonPartialIndexObject (mapValuesFrom   (firstChild k))
-    Just (!c, _) | isBracketLeft c   -> JsonPartialIndexArray  (arrayValuesFrom (firstChild k))
-    Just _                           -> JsonPartialIndexError "Invalid Json Type"
-    Nothing                          -> JsonPartialIndexError "End of data"
-    where ik                = interests k
-          bpk               = balancedParens k
-          p                 = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
-          remainder         = drop (toCount p) (cursorText k)
-          arrayValuesFrom :: Maybe (JsonCursor BS.ByteString v w) -> [JsonPartialIndex]
-          arrayValuesFrom = L.unfoldr (fmap (jsonPartialIndexAt &&& nextSibling))
-          mapValuesFrom j   = pairwise (arrayValuesFrom j) >>= asField
-          pairwise (a:b:rs) = (a, b) : pairwise rs
-          pairwise _        = []
-          asField (a, b)    = case a of
-                                JsonPartialIndexString s -> [(s, b)]
-                                _                        -> []
-
-instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonIndexAt (JsonCursor BS.ByteString v w) where
-  jsonIndexAt k = case uncons remainder of
-    Just (!c, _) | isLeadingDigit2 c -> Right (JsonIndexNumber  remainder)
-    Just (!c, _) | isQuotDbl c       -> Right (JsonIndexString  remainder)
-    Just (!c, _) | isChar_t c        -> Right (JsonIndexBool    True)
-    Just (!c, _) | isChar_f c        -> Right (JsonIndexBool    False)
-    Just (!c, _) | isChar_n c        -> Right  JsonIndexNull
-    Just (!c, _) | isBraceLeft c     -> JsonIndexObject <$> mapValuesFrom   (firstChild k)
-    Just (!c, _) | isBracketLeft c   -> JsonIndexArray  <$> arrayValuesFrom (firstChild k)
-    Just _                           -> Left (DecodeError "Invalid Json Type")
-    Nothing                          -> Left (DecodeError "End of data"      )
-    where ik                = interests k
-          bpk               = balancedParens k
-          p                 = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
-          remainder         = drop (toCount p) (cursorText k)
-          arrayValuesFrom j = sequence (L.unfoldr (fmap (jsonIndexAt &&& nextSibling)) j)
-          mapValuesFrom j   = (pairwise >=> asField) <$> arrayValuesFrom j
-          pairwise (a:b:rs) = (a, b) : pairwise rs
-          pairwise _        = []
-          asField (a, b)    = case a of
-                                JsonIndexString s -> [(s, b)]
-                                _                 -> []
-
-instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonPartialValueAt (JsonCursor BS.ByteString v w) where
-  jsonPartialJsonValueAt = jsonPartialJsonValueAt . jsonPartialIndexAt
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Fast.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Fast.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Fast.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Fast
-  ( makeCursor
-  ) where
-
-import Data.Word
-import Foreign.ForeignPtr
-import HaskellWorks.Data.FromForeignRegion
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.RankSelect.Poppy512
-
-import qualified Data.ByteString                                       as BS
-import qualified Data.ByteString.Char8                                 as BSC
-import qualified Data.ByteString.Internal                              as BSI
-import qualified Data.Vector.Storable                                  as DVS
-import qualified HaskellWorks.Data.BalancedParens                      as BP
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.IbBp as J
-
-class MakeCursor a where
-  makeCursor :: a -> JsonCursor BS.ByteString Poppy512 (BP.SimpleBalancedParens (DVS.Vector Word64))
-
-instance MakeCursor BS.ByteString where
-  makeCursor bs = JsonCursor
-    { cursorText      = bs
-    , interests       = makePoppy512 ib
-    , balancedParens  = BP.SimpleBalancedParens bp
-    , cursorRank      = 1
-    }
-    where J.IbBp ib bp = J.toIbBp bs
-
-instance MakeCursor String where
-  makeCursor = makeCursor . BSC.pack
-
-instance MakeCursor ForeignRegion where
-  makeCursor (fptr, offset, size) = makeCursor (BSI.fromForeignPtr (castForeignPtr fptr) offset size)
-
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Index.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Index.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Index.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-module HaskellWorks.Data.Json.Backend.Standard.Index
-  ( indexJson
-  ) where
-
-import Data.Word
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-
-import qualified Data.ByteString                                     as BS
-import qualified Data.Vector.Storable                                as DVS
-import qualified HaskellWorks.Data.ByteString                        as BS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Load.Cursor as L
-
-indexJson :: String -> IO ()
-indexJson filename = do
-  JsonCursor _ ib (SimpleBalancedParens bp) _ <- L.loadCursor filename
-  let wib = DVS.unsafeCast ib :: DVS.Vector Word8
-  let wbp = DVS.unsafeCast bp :: DVS.Vector Word8
-  BS.writeFile (filename ++ ".ib.idx") (BS.toByteString wib)
-  BS.writeFile (filename ++ ".bp.idx") (BS.toByteString wbp)
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Load/Cursor.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Load/Cursor.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Load/Cursor.hs
+++ /dev/null
@@ -1,53 +0,0 @@
-{-# LANGUAGE BangPatterns #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Load.Cursor
-  ( loadCursor
-  , loadCursorWithIndex
-  , loadCursorWithPoppy512Index
-  , loadCursorWithCsPoppyIndex
-  , loadCursorWithPoppy512Index2
-  ) where
-
-import Data.Word
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Backend.Standard.Load.Raw
-import HaskellWorks.Data.RankSelect.CsPoppy
-import HaskellWorks.Data.RankSelect.Poppy512
-
-import qualified Data.ByteString                              as BS
-import qualified Data.ByteString.Internal                     as BSI
-import qualified Data.Vector.Storable                         as DVS
-import qualified HaskellWorks.Data.ByteString                 as BS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Slow as SLOW
-
-loadCursor :: String -> IO (JsonCursor BS.ByteString (DVS.Vector Word64) (SimpleBalancedParens (DVS.Vector Word64)))
-loadCursor path = do
-  bs <- BS.mmap path
-  let !cursor = SLOW.makeCursor bs
-  return cursor
-
-loadCursorWithIndex :: String -> IO (JsonCursor BSI.ByteString (DVS.Vector Word64) (SimpleBalancedParens (DVS.Vector Word64)))
-loadCursorWithIndex filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS jsonIb (SimpleBalancedParens jsonBp) 1
-  return cursor
-
-loadCursorWithPoppy512Index :: String -> IO (JsonCursor BSI.ByteString Poppy512 (SimpleBalancedParens (DVS.Vector Word64)))
-loadCursorWithPoppy512Index filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (makePoppy512 jsonIb) (SimpleBalancedParens jsonBp) 1
-  return cursor
-
-loadCursorWithCsPoppyIndex :: String -> IO (JsonCursor BSI.ByteString CsPoppy (SimpleBalancedParens (DVS.Vector Word64)))
-loadCursorWithCsPoppyIndex filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (makeCsPoppy jsonIb) (SimpleBalancedParens jsonBp) 1
-  return cursor
-
-loadCursorWithPoppy512Index2 :: String -> IO (JsonCursor BSI.ByteString Poppy512 (SimpleBalancedParens Poppy512))
-loadCursorWithPoppy512Index2 filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (makePoppy512 jsonIb) (SimpleBalancedParens (makePoppy512 jsonBp)) 1
-                :: JsonCursor BSI.ByteString Poppy512 (SimpleBalancedParens Poppy512)
-  return cursor
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Load/Partial.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Load/Partial.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Load/Partial.hs
+++ /dev/null
@@ -1,54 +0,0 @@
-{-# LANGUAGE BangPatterns        #-}
-{-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Load.Partial
-  ( loadPartial
-  , loadPartialWithCsPoppyIndex
-  , loadPartialWithIndex
-  , loadPartialWithPoppy512Index
-  , loadPartialWithPoppy512Index2
-  ) where
-
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Bits.BitShown
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Backend.Standard.Load.Raw
-import HaskellWorks.Data.Json.Internal.PartialIndex
-import HaskellWorks.Data.Json.PartialValue
-import HaskellWorks.Data.RankSelect.CsPoppy
-import HaskellWorks.Data.RankSelect.Poppy512
-
-import qualified Data.ByteString.Internal as BSI
-
-loadPartialWithIndex :: String -> IO JsonPartialValue
-loadPartialWithIndex filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (BitShown jsonIb) (SimpleBalancedParens jsonBp) 1
-  let !jsonResult = jsonPartialJsonValueAt (jsonPartialIndexAt cursor)
-  return jsonResult
-
-loadPartialWithPoppy512Index :: String -> IO JsonPartialValue
-loadPartialWithPoppy512Index filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (makePoppy512 jsonIb) (SimpleBalancedParens jsonBp) 1
-  let !jsonResult = jsonPartialJsonValueAt (jsonPartialIndexAt cursor)
-  return jsonResult
-
-loadPartialWithCsPoppyIndex :: String -> IO JsonPartialValue
-loadPartialWithCsPoppyIndex filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (makeCsPoppy jsonIb) (SimpleBalancedParens jsonBp) 1
-  let !jsonResult = jsonPartialJsonValueAt (jsonPartialIndexAt cursor)
-  return jsonResult
-
-loadPartialWithPoppy512Index2 :: String -> IO JsonPartialValue
-loadPartialWithPoppy512Index2 filename = do
-  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
-  let cursor = JsonCursor jsonBS (makePoppy512 jsonIb) (SimpleBalancedParens (makePoppy512 jsonBp)) 1
-                :: JsonCursor BSI.ByteString Poppy512 (SimpleBalancedParens Poppy512)
-  let !jsonResult = jsonPartialJsonValueAt (jsonPartialIndexAt cursor)
-  return jsonResult
-
-loadPartial :: String -> IO JsonPartialValue
-loadPartial = loadPartialWithCsPoppyIndex
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Load/Raw.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Load/Raw.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Load/Raw.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-module HaskellWorks.Data.Json.Backend.Standard.Load.Raw
-  ( loadRawWithIndex
-  ) where
-
-import Data.Word
-import HaskellWorks.Data.FromForeignRegion
-import System.IO.MMap
-
-import qualified Data.ByteString      as BS
-import qualified Data.Vector.Storable as DVS
-
-loadRawWithIndex :: String -> IO (BS.ByteString, DVS.Vector Word64, DVS.Vector Word64)
-loadRawWithIndex filename = do
-  jsonFr    <- mmapFileForeignPtr filename ReadOnly Nothing
-  jsonIbFr  <- mmapFileForeignPtr (filename ++ ".ib.idx") ReadOnly Nothing
-  jsonBpFr  <- mmapFileForeignPtr (filename ++ ".bp.idx") ReadOnly Nothing
-  let jsonBS  = fromForeignRegion jsonFr    :: BS.ByteString
-  let jsonIb  = fromForeignRegion jsonIbFr  :: DVS.Vector Word64
-  let jsonBp  = fromForeignRegion jsonBpFr  :: DVS.Vector Word64
-  return (jsonBS, jsonIb, jsonBp)
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/SemiIndex.hs b/src/HaskellWorks/Data/Json/Backend/Standard/SemiIndex.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/SemiIndex.hs
+++ /dev/null
@@ -1,269 +0,0 @@
-{-# LANGUAGE BinaryLiterals      #-}
-{-# LANGUAGE DeriveFunctor       #-}
-{-# LANGUAGE DeriveTraversable   #-}
-{-# LANGUAGE InstanceSigs        #-}
-{-# LANGUAGE MultiWayIf          #-}
-{-# LANGUAGE RankNTypes          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.SemiIndex
-  ( semiIndexBuilder
-  , SemiIndex(..)
-  , PreSiChunk(..)
-  , SiChunk(..)
-  , buildSemiIndex
-  , State(..)
-  , buildFromByteString2
-  , buildFromByteString3
-  , toIbBpBuilders
-  ) where
-
-import Control.Monad.ST
-import Data.Bits.Pdep
-import Data.Bits.Pext
-import Data.Word
-import Foreign.Storable                                              (Storable (..))
-import HaskellWorks.Data.Bits.BitWise
-import HaskellWorks.Data.Bits.PopCount.PopCount1
-import HaskellWorks.Data.Json.Internal.Backend.Standard.StateMachine (IntState (..), State (..))
-import HaskellWorks.Data.Vector.AsVector64
-
-import qualified Data.ByteString                                                     as BS
-import qualified Data.ByteString.Builder                                             as B
-import qualified Data.ByteString.Lazy                                                as LBS
-import qualified Data.ByteString.Unsafe                                              as BSU
-import qualified Data.Vector.Storable                                                as DVS
-import qualified Data.Vector.Storable.Mutable                                        as DVSM
-import qualified HaskellWorks.Data.Bits.Writer.Storable                              as W
-import qualified HaskellWorks.Data.ByteString                                        as BS
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.Blank              as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson        as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex          as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.StateMachine       as SM
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.ToBalancedParens64 as J
-import qualified HaskellWorks.Data.Json.Internal.Word8                               as W8
-
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-
-data PreSiChunk v = PreSiChunk
-  { preSiChunkIb   :: !v -- interest bits
-  , preSiChunkBpOp :: !v -- balanced parens interest bits
-  , preSiChunkBpCl :: !v -- balanced parens open close
-  } deriving (Functor, Traversable, Foldable)
-
-data SiChunk v = SiChunk
-  { siChunkIb :: !v -- interest bits
-  , siChunkBp :: !v -- balanced parens open close
-  } deriving (Functor, Traversable, Foldable)
-
-data SemiIndex v = SemiIndex
-  { semiIndexIb :: !v
-  , semiIndexBp :: !v
-  } deriving (Functor, Traversable, Foldable)
-
-semiIndexBuilder :: LBS.ByteString -> SemiIndex B.Builder
-semiIndexBuilder lbs = SemiIndex (B.lazyByteString ibs) (B.byteString (BS.toByteString bps))
-  where blankedJson = J.blankJson (LBS.toChunks lbs)
-        ibs = LBS.fromChunks (J.blankedJsonToInterestBits blankedJson)
-        bps = J.toBalancedParens64 (J.BlankedJson blankedJson)
-{-# INLINE semiIndexBuilder #-}
-
-buildSemiIndex :: BS.ByteString -> SemiIndex (DVS.Vector Word64)
-buildSemiIndex bs = DVS.createT $ do
-  let len = (BS.length bs + 7) `div` 8
-  mib <- W.newWriter len
-  mbp <- W.newWriter (len * 2)
-  buildFromByteString mib mbp bs 0 InJson
-{-# INLINE buildSemiIndex #-}
-
-buildFromByteString :: W.Writer s -> W.Writer s -> BS.ByteString -> Int -> State -> ST s (SemiIndex (DVS.MVector s Word64))
-buildFromByteString ib bp bs i = go
-  where go state = if i < BS.length bs
-          then do
-            let c = BSU.unsafeIndex bs i
-            case state of
-              InJson -> if
-                | c == W8.openBracket || c == W8.openBrace -> do
-                  W.unsafeWriteBit ib 1
-                  W.unsafeWriteBit bp 1
-                  buildFromByteString ib bp bs (i + 1) InJson
-                | c == W8.closeBracket || c == W8.closeBrace -> do
-                  W.unsafeWriteBit bp 0
-                  W.unsafeWriteBit ib 0
-                  buildFromByteString ib bp bs (i + 1) InJson
-                | c == W8.comma || c == W8.colon -> do
-                  W.unsafeWriteBit ib 0
-                  buildFromByteString ib bp bs (i + 1) InJson
-                | W8.isAlphabetic c || W8.isDigit c || W8.isPeriod c || W8.isMinus c || W8.isPlus c -> do
-                  W.unsafeWriteBit ib 1
-                  W.unsafeWriteBit bp 1
-                  W.unsafeWriteBit bp 0
-                  buildFromByteString ib bp bs (i + 1) InValue
-                | c == W8.doubleQuote -> do
-                  W.unsafeWriteBit ib 1
-                  W.unsafeWriteBit bp 1
-                  W.unsafeWriteBit bp 0
-                  buildFromByteString ib bp bs (i + 1) InString
-                | otherwise -> do
-                  W.unsafeWriteBit ib 0
-                  buildFromByteString ib bp bs (i + 1) InJson
-              InString -> do
-                W.unsafeWriteBit ib 0
-                let newContext = if
-                      | c == W8.doubleQuote -> InJson
-                      | c == W8.backSlash   -> InEscape
-                      | otherwise           -> InString
-                buildFromByteString ib bp bs (i + 1) newContext
-              InEscape -> do
-                W.unsafeWriteBit ib 0
-                buildFromByteString ib bp bs (i + 1) InString
-              InValue -> if
-                | W8.isAlphabetic c || W8.isDigit c || W8.isPeriod c || W8.isMinus c || W8.isPlus c -> do
-                  W.unsafeWriteBit ib 0
-                  buildFromByteString ib bp bs (i + 1) InValue
-                | otherwise -> go InJson
-          else do
-            ibv <- W.written ib
-            bpv <- W.written bp
-            return (SemiIndex ibv bpv)
-{-# INLINE buildFromByteString #-}
-
-constructSI :: forall a s. Storable a => Int -> (Int -> s -> (s, a)) -> s -> (s, DVS.Vector a)
-constructSI n f state = DVS.createT $ do
-  mv <- DVSM.unsafeNew n
-  state' <- go 0 state mv
-  return (state', mv)
-  where go :: Int -> s -> DVSM.MVector t a -> ST t s
-        go i s mv = if i < DVSM.length mv
-          then do
-            let (s', a) = f i s
-            DVSM.unsafeWrite mv i a
-            go (i + 1) s' mv
-          else return s
-{-# INLINE constructSI #-}
-
-buildFromByteString2 :: [BS.ByteString] -> [DVS.Vector Word64]
-buildFromByteString2 = go (IntState (fromEnum InJson))
-  where go :: IntState -> [BS.ByteString] -> [DVS.Vector Word64]
-        go s (bs:bss) = v:go s' bss
-          where (s', v) = constructSI (BS.length bs `div` 16) f s -- TODO adjust length
-                f :: Int -> IntState -> (IntState, Word64)
-                f i s'' = let j = i * 16 in transition16 s''
-                  (BSU.unsafeIndex bs  j      )
-                  (BSU.unsafeIndex bs (j +  1))
-                  (BSU.unsafeIndex bs (j +  2))
-                  (BSU.unsafeIndex bs (j +  3))
-                  (BSU.unsafeIndex bs (j +  4))
-                  (BSU.unsafeIndex bs (j +  5))
-                  (BSU.unsafeIndex bs (j +  6))
-                  (BSU.unsafeIndex bs (j +  7))
-                  (BSU.unsafeIndex bs (j +  8))
-                  (BSU.unsafeIndex bs (j +  9))
-                  (BSU.unsafeIndex bs (j + 10))
-                  (BSU.unsafeIndex bs (j + 11))
-                  (BSU.unsafeIndex bs (j + 12))
-                  (BSU.unsafeIndex bs (j + 13))
-                  (BSU.unsafeIndex bs (j + 14))
-                  (BSU.unsafeIndex bs (j + 15))
-        go _ [] = []
-{-# INLINE buildFromByteString2 #-}
-
-transition16 :: IntState
-  -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8
-  -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8
-  -> (IntState, Word64)
-transition16 s  a b c d  e f g h  i j k l  m n o p = (sp, w)
-  where (sa, wa) = transition1 s  a
-        (sb, wb) = transition1 sa b
-        (sc, wc) = transition1 sb c
-        (sd, wd) = transition1 sc d
-        (se, we) = transition1 sd e
-        (sf, wf) = transition1 se f
-        (sg, wg) = transition1 sf g
-        (sh, wh) = transition1 sg h
-        (si, wi) = transition1 sh i
-        (sj, wj) = transition1 si j
-        (sk, wk) = transition1 sj k
-        (sl, wl) = transition1 sk l
-        (sm, wm) = transition1 sl m
-        (sn, wn) = transition1 sm n
-        (so, wo) = transition1 sn o
-        (sp, wp) = transition1 so p
-        w = (fromIntegral wa       ) .|.
-            (fromIntegral wb .<.  4) .|.
-            (fromIntegral wc .<.  8) .|.
-            (fromIntegral wd .<. 12) .|.
-            (fromIntegral we .<. 16) .|.
-            (fromIntegral wf .<. 20) .|.
-            (fromIntegral wg .<. 24) .|.
-            (fromIntegral wh .<. 28) .|.
-            (fromIntegral wi .<. 32) .|.
-            (fromIntegral wj .<. 36) .|.
-            (fromIntegral wk .<. 40) .|.
-            (fromIntegral wl .<. 44) .|.
-            (fromIntegral wm .<. 48) .|.
-            (fromIntegral wn .<. 52) .|.
-            (fromIntegral wo .<. 56) .|.
-            (fromIntegral wp .<. 60)
-{-# INLINE transition16 #-}
-
-transition1 :: IntState -> Word8 -> (IntState, Word64)
-transition1 s a = (s', w)
-  where s' =                SM.lookupTransitionTable s (fromIntegral a)
-        w  = fromIntegral $ SM.lookupPhiTable        s (fromIntegral a)
-{-# INLINE transition1 #-}
-
-buildFromByteString3 :: [BS.ByteString] -> [PreSiChunk (DVS.Vector Word64)]
-buildFromByteString3 bss = makePreSiChunk <$> buildFromByteString2 bss
-  where makePreSiChunk :: DVS.Vector Word64 -> PreSiChunk (DVS.Vector Word64)
-        makePreSiChunk v = PreSiChunk (makeIb v) (makeBpOp v) (makeBpCl v)
-        makeIb :: DVS.Vector Word64 -> DVS.Vector Word64
-        makeIb v = asVector64 $ BS.toByteString $ DVS.constructN (DVS.length v) go
-          where go :: DVS.Vector Word16 -> Word16
-                go u = let ui = DVS.length u in fromIntegral (pext (DVS.unsafeIndex v ui) 0x4444444444444444)
-        makeBpOp :: DVS.Vector Word64 -> DVS.Vector Word64
-        makeBpOp v = asVector64 $ BS.toByteString $ DVS.constructN (DVS.length v) go
-          where go :: DVS.Vector Word16 -> Word16
-                go u = let ui = DVS.length u in fromIntegral (pext (DVS.unsafeIndex v ui) 0x2222222222222222)
-        makeBpCl v = asVector64 $ BS.toByteString $ DVS.constructN (DVS.length v) go
-          where go :: DVS.Vector Word16 -> Word16
-                go u = let ui = DVS.length u in fromIntegral (pext (DVS.unsafeIndex v ui) 0x1111111111111111)
-
-toIbBpBuilders :: [PreSiChunk (DVS.Vector Word64)] -> [SiChunk (DVS.Vector Word64)]
-toIbBpBuilders = go 0 0
-  where go :: Word64 -> Word64 -> [PreSiChunk (DVS.Vector Word64)] -> [SiChunk (DVS.Vector Word64)]
-        go b n (PreSiChunk ib bpOp bpCl:cs) = SiChunk ib bp: go b' n' cs
-          where ((b', n'), bp) = mkBp b n (DVS.unsafeCast bpOp) (DVS.unsafeCast bpCl)
-        go b _ [] = [SiChunk DVS.empty (DVS.singleton b)]
-        mkBp :: Word64 -> Word64 -> DVS.Vector Word32 -> DVS.Vector Word32 -> ((Word64, Word64), DVS.Vector Word64)
-        mkBp b n bpOp bpCl = DVS.createT $ do
-          mv <- DVSM.unsafeNew (DVS.length bpOp)
-          mkBpGo b n bpOp bpCl mv 0 0
-        mkBpGo :: Word64 -> Word64 -> DVS.Vector Word32 -> DVS.Vector Word32 -> DVS.MVector s Word64 -> Int -> Int -> ST s ((Word64, Word64), DVS.MVector s Word64)
-        mkBpGo b n bpOp bpCl mv vi mvi = if vi < DVS.length bpOp
-          then do
-            let op = DVS.unsafeIndex bpOp vi
-            let cl = DVS.unsafeIndex bpCl vi
-            let (slo, mlo) = compress op cl -- slo: source lo, mlo: mask lo
-            let wb = pext slo mlo
-            let wn = popCount1 mlo
-            let tb = (wb .<. n) .|. b
-            let tn = n + wn
-            if tn < 64
-              then do
-                mkBpGo tb tn bpOp bpCl mv (vi + 1) mvi
-              else do
-                DVSM.unsafeWrite mv mvi tb
-                let ub = wb .>. (64 - n)
-                let un = tn - 64
-                mkBpGo ub un bpOp bpCl mv (vi + 1) (mvi + 1)
-          else return ((b, n), DVSM.take mvi mv)
-        compress :: Word32 -> Word32 -> (Word64, Word64)
-        compress op cl = (sw, mw)
-          where iop = pdep (fromIntegral op :: Word64) 0x5555555555555555 -- interleaved open
-                icl = pdep (fromIntegral cl :: Word64) 0xaaaaaaaaaaaaaaaa -- interleaved close
-                ioc = iop .|. icl                                         -- interleaved open/close
-                sw  = pext iop ioc
-                pc  = popCount1 ioc
-                mw  = (1 .<. pc) - 1
diff --git a/src/HaskellWorks/Data/Json/Backend/Standard/Slow.hs b/src/HaskellWorks/Data/Json/Backend/Standard/Slow.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Backend/Standard/Slow.hs
+++ /dev/null
@@ -1,36 +0,0 @@
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Slow
-  ( makeCursor
-  ) where
-
-import Data.Word
-import Foreign.ForeignPtr
-import HaskellWorks.Data.FromForeignRegion
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-
-import qualified Data.ByteString                                       as BS
-import qualified Data.ByteString.Char8                                 as BSC
-import qualified Data.ByteString.Internal                              as BSI
-import qualified Data.Vector.Storable                                  as DVS
-import qualified HaskellWorks.Data.BalancedParens                      as BP
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.IbBp as J
-
-class MakeCursor a where
-  makeCursor :: a -> JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))
-
-instance MakeCursor BS.ByteString where
-  makeCursor bs = JsonCursor
-    { cursorText      = bs
-    , interests       = ib
-    , balancedParens  = BP.SimpleBalancedParens bp
-    , cursorRank      = 1
-    }
-    where J.IbBp ib bp = J.toIbBp bs
-
-instance MakeCursor String where
-  makeCursor = makeCursor . BSC.pack
-
-instance MakeCursor ForeignRegion where
-  makeCursor (fptr, offset, size) = makeCursor (BSI.fromForeignPtr (castForeignPtr fptr) offset size)
diff --git a/src/HaskellWorks/Data/Json/FromValue.hs b/src/HaskellWorks/Data/Json/FromValue.hs
--- a/src/HaskellWorks/Data/Json/FromValue.hs
+++ b/src/HaskellWorks/Data/Json/FromValue.hs
@@ -1,11 +1,13 @@
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 module HaskellWorks.Data.Json.FromValue where
 
+import Data.Text                          (Text)
 import HaskellWorks.Data.Json.DecodeError
 import HaskellWorks.Data.Json.Value
 
+import qualified Data.Text as T
+
 class FromJsonValue a where
   fromJsonValue :: JsonValue -> Either DecodeError a
 
@@ -14,28 +16,33 @@
 
 instance FromJsonValue String where
   fromJsonValue v = case v of
-    JsonString r  -> Right r
-    _             -> Left (DecodeError "Not a string")
+    JsonString r -> Right (T.unpack r)
+    _            -> Left (DecodeError "Not a string")
 
+instance FromJsonValue Text where
+  fromJsonValue v = case v of
+    JsonString r -> Right r
+    _            -> Left (DecodeError "Not a string")
+
 instance FromJsonValue Int where
   fromJsonValue v = case v of
-    JsonNumber r  -> Right (floor r)
-    _             -> Left (DecodeError "Not an integer")
+    JsonNumber r -> Right (floor r)
+    _            -> Left (DecodeError "Not an integer")
 
 instance FromJsonValue Double where
   fromJsonValue v = case v of
-    JsonNumber r  -> Right r
-    _             -> Left (DecodeError "Not a double")
+    JsonNumber r -> Right r
+    _            -> Left (DecodeError "Not a double")
 
 instance FromJsonValue Bool where
   fromJsonValue v = case v of
-    JsonBool r    -> Right r
-    _             -> Left (DecodeError "Not a boolean")
+    JsonBool r -> Right r
+    _          -> Left (DecodeError "Not a boolean")
 
 instance FromJsonValue a => FromJsonValue [a] where
   fromJsonValue v = case v of
-    JsonArray xs  -> mapM fromJsonValue xs
-    _             -> Left (DecodeError "Not an array")
+    JsonArray xs -> mapM fromJsonValue xs
+    _            -> Left (DecodeError "Not an array")
 
 instance (FromJsonValue a, FromJsonValue b) => FromJsonValue (a, b) where
   fromJsonValue v = case v of
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Simple/IbBp.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Simple/IbBp.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Simple/IbBp.hs
+++ /dev/null
@@ -1,10 +0,0 @@
-module HaskellWorks.Data.Json.Internal.Backend.Simple.IbBp where
-
-import Data.Word
-
-import qualified Data.Vector.Storable as DVS
-
-data IbBp = IbBp
-  { ib :: DVS.Vector Word64
-  , bp :: DVS.Vector Word64
-  }
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Simple/ToIbBp.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Simple/ToIbBp.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Simple/ToIbBp.hs
+++ /dev/null
@@ -1,12 +0,0 @@
-module HaskellWorks.Data.Json.Internal.Backend.Simple.ToIbBp where
-
-import qualified Data.ByteString                                     as BS
-import qualified HaskellWorks.Data.Json.Backend.Simple.SemiIndex     as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Simple.IbBp as Z
-
-class ToIbBp a where
-  toIbBp :: a -> Z.IbBp
-
-instance ToIbBp BS.ByteString where
-  toIbBp bs = Z.IbBp ib bp
-    where J.SemiIndex _ ib bp = J.buildSemiIndex bs
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Blank.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Blank.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Blank.hs
+++ /dev/null
@@ -1,56 +0,0 @@
-{-# LANGUAGE BangPatterns #-}
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.Blank
-  ( blankJson
-  ) where
-
-import Data.ByteString                       as BS
-import Data.Word
-import Data.Word8
-import HaskellWorks.Data.Json.Internal.Word8
-import Prelude                               as P
-
-data BlankState
-  = Escaped
-  | InJson
-  | InString
-  | InNumber
-  | InIdent
-
-blankJson :: [BS.ByteString] -> [BS.ByteString]
-blankJson = blankJson' InJson
-
-blankJson' :: BlankState -> [BS.ByteString] -> [BS.ByteString]
-blankJson' lastState as = case as of
-  (bs:bss) ->
-      let (!cs, Just (!nextState, _)) = unfoldrN (BS.length bs) blankByteString (lastState, bs) in
-      cs:blankJson' nextState bss
-  [] -> []
-  where
-    blankByteString :: (BlankState, ByteString) -> Maybe (Word8, (BlankState, ByteString))
-    blankByteString (InJson, bs) = case BS.uncons bs of
-      Just (!c, !cs) | isLeadingDigit c -> Just (_1          , (InNumber , cs))
-      Just (!c, !cs) | c == _quotedbl   -> Just (_parenleft  , (InString , cs))
-      Just (!c, !cs) | isAlphabetic c   -> Just (c           , (InIdent  , cs))
-      Just (!c, !cs)                    -> Just (c           , (InJson   , cs))
-      Nothing                           -> Nothing
-    blankByteString (InString, bs) = case BS.uncons bs of
-      Just (!c, !cs) | c == _backslash -> Just (_space      , (Escaped  , cs))
-      Just (!c, !cs) | c == _quotedbl  -> Just (_parenright , (InJson   , cs))
-      Just (_ , !cs)                   -> Just (_space      , (InString , cs))
-      Nothing                          -> Nothing
-    blankByteString (Escaped, bs) = case BS.uncons bs of
-      Just (_, !cs) -> Just (_space, (InString, cs))
-      Nothing       -> Nothing
-    blankByteString (InNumber, bs) = case BS.uncons bs of
-      Just (!c, !cs) | isTrailingDigit c -> Just (_0          , (InNumber , cs))
-      Just (!c, !cs) | c == _quotedbl    -> Just (_parenleft  , (InString , cs))
-      Just (!c, !cs) | isAlphabetic c    -> Just (c           , (InIdent  , cs))
-      Just (!c, !cs)                     -> Just (c           , (InJson   , cs))
-      Nothing                            -> Nothing
-    blankByteString (InIdent, bs) = case BS.uncons bs of
-      Just (!c, !cs) | isAlphabetic c   -> Just (_underscore , (InIdent  , cs))
-      Just (!c, !cs) | isLeadingDigit c -> Just (_1          , (InNumber , cs))
-      Just (!c, !cs) | c == _quotedbl   -> Just (_parenleft  , (InString , cs))
-      Just (!c, !cs)                    -> Just (c           , (InJson   , cs))
-      Nothing                           -> Nothing
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/BlankedJson.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/BlankedJson.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/BlankedJson.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson
-  ( BlankedJson(..)
-  , ToBlankedJson(..)
-  , toBlankedJsonTyped
-  ) where
-
-import HaskellWorks.Data.ByteString
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Blank
-
-import qualified Data.ByteString as BS
-
-newtype BlankedJson = BlankedJson
-  { unBlankedJson :: [BS.ByteString]
-  } deriving (Eq, Show)
-
-class ToBlankedJson a where
-  toBlankedJson :: a -> [BS.ByteString]
-
-instance ToBlankedJson BS.ByteString where
-  toBlankedJson bs = blankJson (chunkedBy 4096 bs)
-
-toBlankedJsonTyped :: ToBlankedJson a => a -> BlankedJson
-toBlankedJsonTyped = BlankedJson . toBlankedJson
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Cursor/Token.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Cursor/Token.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Cursor/Token.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.Cursor.Token
-  ( jsonTokenAt
-  ) where
-
-import Data.ByteString.Internal                                        as BSI
-import HaskellWorks.Data.Bits.BitWise
-import HaskellWorks.Data.Drop
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Token.Tokenize
-import HaskellWorks.Data.Positioning
-import HaskellWorks.Data.RankSelect.Base.Rank1
-import HaskellWorks.Data.RankSelect.Base.Select1
-import Prelude                                                         hiding (drop)
-
-import qualified Data.Attoparsec.ByteString.Char8 as ABC
-
-jsonTokenAt :: (Rank1 w, Select1 v, TestBit w) => JsonCursor ByteString v w -> Maybe (JsonToken String Double)
-jsonTokenAt k = if balancedParens k .?. lastPositionOf (cursorRank k)
-  then case ABC.parse parseJsonToken (drop (toCount (jsonCursorPos k)) (cursorText k)) of
-    ABC.Fail    {}  -> error "Failed to parse token in cursor"
-    ABC.Partial _   -> error "Failed to parse token in cursor"
-    ABC.Done    _ r -> Just r
-  else Nothing
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/IbBp.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/IbBp.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/IbBp.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-module HaskellWorks.Data.Json.Internal.Backend.Standard.IbBp where
-
-import Data.Word
-
-import qualified Data.ByteString                                                     as BS
-import qualified Data.Vector.Storable                                                as DVS
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson        as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.ToBalancedParens64 as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.ToInterestBits64   as J
-
-data IbBp = IbBp
-  { ib :: DVS.Vector Word64
-  , bp :: DVS.Vector Word64
-  }
-
-class ToIbBp a where
-  toIbBp :: a -> IbBp
-
-instance ToIbBp BS.ByteString where
-  toIbBp bs = IbBp
-    { ib = J.toInterestBits64 blankedJson
-    , bp = J.toBalancedParens64 blankedJson
-    }
-    where blankedJson = J.toBlankedJsonTyped bs
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/MakeIndex.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/MakeIndex.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/MakeIndex.hs
+++ /dev/null
@@ -1,134 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes        #-}
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex
-  ( blankedJsonToInterestBits
-  , byteStringToBits
-  , blankedJsonToBalancedParens
-  , compressWordAsBit
-  , interestingWord8s
-  ) where
-
-import Control.Monad
-import Data.Array.Unboxed             ((!))
-import Data.ByteString                (ByteString)
-import Data.Int
-import Data.Word
-import Data.Word8
-import HaskellWorks.Data.Bits.BitWise
-import Prelude                        as P
-
-import qualified Data.Array.Unboxed as A
-import qualified Data.Bits          as BITS
-import qualified Data.ByteString    as BS
-
-interestingWord8s :: A.UArray Word8 Word8
-interestingWord8s = A.array (0, 255) [
-  (w, if w == _bracketleft || w == _braceleft || w == _parenleft || w == _t || w == _f || w == _n || w == _1
-    then 1
-    else 0)
-  | w <- [0 .. 255]]
-
-blankedJsonToInterestBits :: [BS.ByteString] -> [BS.ByteString]
-blankedJsonToInterestBits = blankedJsonToInterestBits' ""
-
-padRight :: Word8 -> Int -> BS.ByteString -> BS.ByteString
-padRight w n bs = if BS.length bs >= n then bs else fst (BS.unfoldrN n gen bs)
-  where gen :: ByteString -> Maybe (Word8, ByteString)
-        gen cs = case BS.uncons cs of
-          Just (c, ds) -> Just (c, ds)
-          Nothing      -> Just (w, BS.empty)
-
-blankedJsonToInterestBits' :: BS.ByteString -> [BS.ByteString] -> [BS.ByteString]
-blankedJsonToInterestBits' rs as = case as of
-  (bs:bss) ->
-      let cs = if BS.length rs /= 0 then BS.concat [rs, bs] else bs in
-      let lencs = BS.length cs in
-      let q = lencs + 7 `quot` 8 in
-      let (ds, es) = BS.splitAt (q * 8) cs in
-      let (fs, _) = BS.unfoldrN q gen ds in
-      fs:blankedJsonToInterestBits' es bss
-  [] -> []
-  where gen :: ByteString -> Maybe (Word8, ByteString)
-        gen ds = if BS.length ds == 0
-          then Nothing
-          else Just ( BS.foldr (\b m -> (interestingWord8s ! b) .|. (m .<. 1)) 0 (padRight 0 8 (BS.take 8 ds))
-                    , BS.drop 8 ds
-                    )
-
-repartitionMod8 :: BS.ByteString -> BS.ByteString -> (BS.ByteString, BS.ByteString)
-repartitionMod8 aBS bBS = (BS.take cLen abBS, BS.drop cLen abBS)
-  where abBS = BS.concat [aBS, bBS]
-        abLen = BS.length abBS
-        cLen = (abLen `div` 8) * 8
-
-compressWordAsBit :: [BS.ByteString] -> [BS.ByteString]
-compressWordAsBit = compressWordAsBit' BS.empty
-
-compressWordAsBit' :: BS.ByteString -> [BS.ByteString] -> [BS.ByteString]
-compressWordAsBit' aBS as = case as of
-  (bBS:bBSs) ->
-    let (cBS, dBS) = repartitionMod8 aBS bBS in
-    let (cs, _) = BS.unfoldrN (BS.length cBS + 7 `div` 8) gen cBS in
-    cs:compressWordAsBit' dBS bBSs
-  [] -> do
-    let (cs, _) = BS.unfoldrN (BS.length aBS + 7 `div` 8) gen aBS
-    [cs]
-  where gen :: ByteString -> Maybe (Word8, ByteString)
-        gen xs = if BS.length xs == 0
-          then Nothing
-          else Just ( BS.foldr (\b m -> ((b .&. 1) .|. (m .<. 1))) 0 (padRight 0 8 (BS.take 8 xs))
-                    , BS.drop 8 xs
-                    )
-
-blankedJsonToBalancedParens :: [BS.ByteString] -> [BS.ByteString]
-blankedJsonToBalancedParens as = case as of
-  (bs:bss) ->
-    let (cs, _) = BS.unfoldrN (BS.length bs * 2) gen (Nothing, bs) in
-    cs:blankedJsonToBalancedParens bss
-  [] -> []
-  where gen :: (Maybe Bool, ByteString) -> Maybe (Word8, (Maybe Bool, ByteString))
-        gen (Just True  , bs) = Just (0xFF, (Nothing, bs))
-        gen (Just False , bs) = Just (0x00, (Nothing, bs))
-        gen (Nothing    , bs) = case BS.uncons bs of
-          Just (c, cs) -> case balancedParensOf c of
-            MiniN  -> gen         (Nothing    , cs)
-            MiniT  -> Just (0xFF, (Nothing    , cs))
-            MiniF  -> Just (0x00, (Nothing    , cs))
-            MiniTF -> Just (0xFF, (Just False , cs))
-          Nothing   -> Nothing
-
-data MiniBP = MiniN | MiniT | MiniF | MiniTF
-
-balancedParensOf :: Word8 -> MiniBP
-balancedParensOf c = case c of
-    d | d == _braceleft    -> MiniT
-    d | d == _braceright   -> MiniF
-    d | d == _bracketleft  -> MiniT
-    d | d == _bracketright -> MiniF
-    d | d == _parenleft    -> MiniT
-    d | d == _parenright   -> MiniF
-    d | d == _t            -> MiniTF
-    d | d == _f            -> MiniTF
-    d | d == _1            -> MiniTF
-    d | d == _n            -> MiniTF
-    _                      -> MiniN
-
-yieldBitsOfWord8 :: Word8 -> [Bool] -> [Bool]
-yieldBitsOfWord8 w =
-  (((w .&. BITS.bit 0) /= 0):) .
-  (((w .&. BITS.bit 1) /= 0):) .
-  (((w .&. BITS.bit 2) /= 0):) .
-  (((w .&. BITS.bit 3) /= 0):) .
-  (((w .&. BITS.bit 4) /= 0):) .
-  (((w .&. BITS.bit 5) /= 0):) .
-  (((w .&. BITS.bit 6) /= 0):) .
-  (((w .&. BITS.bit 7) /= 0):)
-
-yieldBitsofWord8s :: [Word8] -> [Bool] -> [Bool]
-yieldBitsofWord8s = P.foldr ((>>) . yieldBitsOfWord8) id
-
-byteStringToBits :: [BS.ByteString] -> [Bool] -> [Bool]
-byteStringToBits as = case as of
-  (bs:bss) -> yieldBitsofWord8s (BS.unpack bs) . byteStringToBits bss
-  []       -> id
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/StateMachine.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/StateMachine.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/StateMachine.hs
+++ /dev/null
@@ -1,109 +0,0 @@
-{-# LANGUAGE BinaryLiterals             #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE OverloadedStrings          #-}
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.StateMachine
-  ( lookupPhiTable
-  , lookupTransitionTable
-  , phiTable
-  , phiTableSimd
-  , transitionTable
-  , transitionTableSimd
-  , IntState(..)
-  , State(..)
-  ) where
-
-import Data.Word
-import HaskellWorks.Data.Bits.BitWise
-
-import qualified Data.Vector                           as DV
-import qualified Data.Vector.Storable                  as DVS
-import qualified HaskellWorks.Data.Json.Internal.Word8 as W8
-
-{-# ANN module ("HLint: ignore Redundant guard"  :: String) #-}
-
-newtype IntState = IntState Int deriving (Eq, Ord, Show, Num)
-
-data State = InJson | InString | InEscape | InValue deriving (Eq, Enum, Bounded, Show)
-
-phiTable :: DV.Vector (DVS.Vector Word8)
-phiTable = DV.constructN 5 gos
-  where gos :: DV.Vector (DVS.Vector Word8) -> DVS.Vector Word8
-        gos v = DVS.constructN 256 go
-          where vi = DV.length v
-                go :: DVS.Vector Word8 -> Word8
-                go u = fromIntegral (snd (stateMachine (fromIntegral ui) (toEnum vi)))
-                  where ui = DVS.length u
-{-# NOINLINE phiTable #-}
-
-phiTable2 :: DVS.Vector Word8
-phiTable2 = DVS.constructN (4 * fromIntegral iLen) go
-  where iLen = 256 :: Int
-        go :: DVS.Vector Word8 -> Word8
-        go u = fromIntegral (snd (stateMachine (fromIntegral ui) (toEnum (fromIntegral uj))))
-          where (uj, ui) = fromIntegral (DVS.length u) `divMod` iLen
-{-# NOINLINE phiTable2 #-}
-
-lookupPhiTable :: IntState -> Word8 -> Word8
-lookupPhiTable (IntState s) w = DVS.unsafeIndex phiTable2 (s * 256 + fromIntegral w)
-{-# INLINE lookupPhiTable #-}
-
-phiTableSimd :: DVS.Vector Word32
-phiTableSimd = DVS.constructN 256 go
-  where go :: DVS.Vector Word32 -> Word32
-        go v =  (snd (stateMachine vi InJson  ) .<.  0) .|.
-                (snd (stateMachine vi InString) .<.  8) .|.
-                (snd (stateMachine vi InEscape) .<. 16) .|.
-                (snd (stateMachine vi InValue ) .<. 24)
-          where vi = fromIntegral (DVS.length v)
-{-# NOINLINE phiTableSimd #-}
-
-transitionTable :: DV.Vector (DVS.Vector Word8)
-transitionTable = DV.constructN 5 gos
-  where gos :: DV.Vector (DVS.Vector Word8) -> DVS.Vector Word8
-        gos v = DVS.constructN 256 go
-          where vi = DV.length v
-                go :: DVS.Vector Word8 -> Word8
-                go u = fromIntegral (fromEnum (fst (stateMachine ui (toEnum vi))))
-                  where ui = fromIntegral (DVS.length u)
-{-# NOINLINE transitionTable #-}
-
-transitionTable2 :: DVS.Vector Word8
-transitionTable2 = DVS.constructN (4 * fromIntegral iLen) go
-  where iLen = 256 :: Int
-        go :: DVS.Vector Word8 -> Word8
-        go u = fromIntegral (fromEnum (fst (stateMachine (fromIntegral ui) (toEnum (fromIntegral uj)))))
-          where (uj, ui) = fromIntegral (DVS.length u) `divMod` iLen
-{-# NOINLINE transitionTable2 #-}
-
-lookupTransitionTable :: IntState -> Word8 -> IntState
-lookupTransitionTable (IntState s) w = fromIntegral (DVS.unsafeIndex transitionTable2 (s * 256 + fromIntegral w))
-{-# INLINE lookupTransitionTable #-}
-
-transitionTableSimd :: DVS.Vector Word64
-transitionTableSimd = DVS.constructN 256 go
-  where go :: DVS.Vector Word64 -> Word64
-        go v =  fromIntegral (fromEnum (fst (stateMachine vi InJson  ))) .|.
-                fromIntegral (fromEnum (fst (stateMachine vi InString))) .|.
-                fromIntegral (fromEnum (fst (stateMachine vi InEscape))) .|.
-                fromIntegral (fromEnum (fst (stateMachine vi InValue )))
-          where vi = fromIntegral (DVS.length v)
-{-# NOINLINE transitionTableSimd #-}
-
-stateMachine :: Word8 -> State -> (State, Word32)
-stateMachine c InJson   | W8.isOpen c         = (InJson  , 0b110)
-stateMachine c InJson   | W8.isClose c        = (InJson  , 0b001)
-stateMachine c InJson   | W8.isDelim c        = (InJson  , 0b000)
-stateMachine c InJson   | W8.isValueChar c    = (InValue , 0b111)
-stateMachine c InJson   | W8.isDoubleQuote c  = (InString, 0b111)
-stateMachine _ InJson   | otherwise           = (InJson  , 0b000)
-stateMachine c InString | W8.isDoubleQuote c  = (InJson  , 0b000)
-stateMachine c InString | W8.isBackSlash c    = (InEscape, 0b000)
-stateMachine _ InString | otherwise           = (InString, 0b000)
-stateMachine _ InEscape | otherwise           = (InString, 0b000)
-stateMachine c InValue  | W8.isOpen c         = (InJson  , 0b110)
-stateMachine c InValue  | W8.isClose c        = (InJson  , 0b001)
-stateMachine c InValue  | W8.isDelim c        = (InJson  , 0b000)
-stateMachine c InValue  | W8.isValueChar c    = (InValue , 0b000)
-stateMachine _ InValue  | otherwise           = (InJson  , 0b000)
-{-# INLINE stateMachine #-}
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/ToBalancedParens64.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/ToBalancedParens64.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/ToBalancedParens64.hs
+++ /dev/null
@@ -1,28 +0,0 @@
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.ToBalancedParens64
-  ( ToBalancedParens64(..)
-  ) where
-
-import Control.Applicative
-import Data.Word
-import HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex
-
-import qualified Data.ByteString.Lazy                                         as LBS
-import qualified Data.Vector.Storable                                         as DVS
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson as J
-
-genBitWordsForever :: LBS.ByteString -> Maybe (Word8, LBS.ByteString)
-genBitWordsForever bs = LBS.uncons bs <|> Just (0, bs)
-{-# INLINE genBitWordsForever #-}
-
-class ToBalancedParens64 a where
-  toBalancedParens64 :: a -> DVS.Vector Word64
-
-instance ToBalancedParens64 J.BlankedJson where
-  toBalancedParens64 (J.BlankedJson bj) = DVS.unsafeCast (DVS.unfoldrN newLen genBitWordsForever bpBS)
-    where bpBS    = LBS.fromChunks (compressWordAsBit (blankedJsonToBalancedParens bj))
-          newLen  = fromIntegral ((LBS.length bpBS + 7) `div` 8 * 8)
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/ToInterestBits64.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/ToInterestBits64.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/ToInterestBits64.hs
+++ /dev/null
@@ -1,31 +0,0 @@
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.ToInterestBits64
-  ( ToInterestBits64(..)
-  ) where
-
-import Control.Applicative
-import Data.ByteString.Internal
-import Data.Word
-import HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex
-
-import qualified Data.ByteString                                              as BS
-import qualified Data.Vector.Storable                                         as DVS
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson as J
-
-class ToInterestBits64 a where
-  toInterestBits64 :: a -> DVS.Vector Word64
-
-instance ToInterestBits64 J.BlankedJson where
-  toInterestBits64 bj = DVS.unsafeCast (DVS.unfoldrN newLen genInterestForever interestBS)
-    where interestBS    = blankedJsonBssToInterestBitsBs (J.unBlankedJson bj)
-          newLen        = (BS.length interestBS + 7) `div` 8 * 8
-
-blankedJsonBssToInterestBitsBs :: [ByteString] -> ByteString
-blankedJsonBssToInterestBitsBs bss = BS.concat $ blankedJsonToInterestBits bss
-
-genInterestForever :: ByteString -> Maybe (Word8, ByteString)
-genInterestForever bs = BS.uncons bs <|> Just (0, bs)
diff --git a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Token/Tokenize.hs b/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Token/Tokenize.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Backend/Standard/Token/Tokenize.hs
+++ /dev/null
@@ -1,165 +0,0 @@
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE TypeSynonymInstances  #-}
-
-module HaskellWorks.Data.Json.Internal.Backend.Standard.Token.Tokenize
-    ( IsChar(..)
-    , JsonToken(..)
-    , ParseJson(..)
-    ) where
-
-import Control.Applicative
-import Data.Bits
-import Data.Char
-import Data.Word
-import Data.Word8
-import HaskellWorks.Data.Char.IsChar
-import HaskellWorks.Data.Json.Internal.Token.Types
-import HaskellWorks.Data.Parser                    ((<?>))
-
-import qualified Data.Attoparsec.ByteString.Char8 as BC
-import qualified Data.Attoparsec.Combinator       as AC
-import qualified Data.Attoparsec.Types            as T
-import qualified Data.ByteString                  as BS
-import qualified HaskellWorks.Data.Parser         as P
-
-hexDigitNumeric :: P.Parser t u => T.Parser t Int
-hexDigitNumeric = do
-  c <- P.satisfyChar (\c -> '0' <= c && c <= '9')
-  return $ ord c - ord '0'
-
-hexDigitAlphaLower :: P.Parser t u => T.Parser t Int
-hexDigitAlphaLower = do
-  c <- P.satisfyChar (\c -> 'a' <= c && c <= 'z')
-  return $ ord c - ord 'a' + 10
-
-hexDigitAlphaUpper :: P.Parser t u => T.Parser t Int
-hexDigitAlphaUpper = do
-  c <- P.satisfyChar (\c -> 'A' <= c && c <= 'Z')
-  return $ ord c - ord 'A' + 10
-
-hexDigit :: P.Parser t u => T.Parser t Int
-hexDigit = hexDigitNumeric <|> hexDigitAlphaLower <|> hexDigitAlphaUpper
-
-class ParseJson t s d where
-  parseJsonTokenString :: T.Parser t (JsonToken s d)
-  parseJsonToken :: T.Parser t (JsonToken s d)
-  parseJsonTokenBraceL :: T.Parser t (JsonToken s d)
-  parseJsonTokenBraceR :: T.Parser t (JsonToken s d)
-  parseJsonTokenBracketL :: T.Parser t (JsonToken s d)
-  parseJsonTokenBracketR :: T.Parser t (JsonToken s d)
-  parseJsonTokenComma :: T.Parser t (JsonToken s d)
-  parseJsonTokenColon :: T.Parser t (JsonToken s d)
-  parseJsonTokenWhitespace :: T.Parser t (JsonToken s d)
-  parseJsonTokenNull :: T.Parser t (JsonToken s d)
-  parseJsonTokenBoolean :: T.Parser t (JsonToken s d)
-  parseJsonTokenDouble :: T.Parser t (JsonToken s d)
-
-  parseJsonToken =
-    parseJsonTokenString     <|>
-    parseJsonTokenBraceL     <|>
-    parseJsonTokenBraceR     <|>
-    parseJsonTokenBracketL   <|>
-    parseJsonTokenBracketR   <|>
-    parseJsonTokenComma      <|>
-    parseJsonTokenColon      <|>
-    parseJsonTokenWhitespace <|>
-    parseJsonTokenNull       <|>
-    parseJsonTokenBoolean    <|>
-    parseJsonTokenDouble
-
-instance ParseJson BS.ByteString String Double where
-  parseJsonTokenBraceL    = P.string "{" >> return JsonTokenBraceL
-  parseJsonTokenBraceR    = P.string "}" >> return JsonTokenBraceR
-  parseJsonTokenBracketL  = P.string "[" >> return JsonTokenBracketL
-  parseJsonTokenBracketR  = P.string "]" >> return JsonTokenBracketR
-  parseJsonTokenComma     = P.string "," >> return JsonTokenComma
-  parseJsonTokenColon     = P.string ":" >> return JsonTokenColon
-  parseJsonTokenNull      = P.string "null" >> return JsonTokenNull
-  parseJsonTokenDouble    = JsonTokenNumber <$> P.rational
-
-  parseJsonTokenString = do
-    _ <- P.string "\""
-    value <- many (verbatimChar <|> escapedChar <|> escapedCode)
-    _ <- P.string "\""
-    return $ JsonTokenString value
-    where
-      verbatimChar  = P.satisfyChar (BC.notInClass "\"\\") <?> "invalid string character"
-      escapedChar   = do
-        _ <- P.string "\\"
-        (   P.char '"'  >> return '"'  ) <|>
-          ( P.char 'b'  >> return '\b' ) <|>
-          ( P.char 'n'  >> return '\n' ) <|>
-          ( P.char 'f'  >> return '\f' ) <|>
-          ( P.char 'r'  >> return '\r' ) <|>
-          ( P.char 't'  >> return '\t' ) <|>
-          ( P.char '\\' >> return '\\' ) <|>
-          ( P.char '\'' >> return '\'' ) <|>
-          ( P.char '/'  >> return '/'  )
-      escapedCode   = do
-        _ <- P.string "\\u"
-        a <- hexDigit
-        b <- hexDigit
-        c <- hexDigit
-        d <- hexDigit
-        return $ chr $ a `shift` 24 .|. b `shift` 16 .|. c `shift` 8 .|. d
-
-  parseJsonTokenWhitespace = do
-    _ <- AC.many1' $ BC.choice [P.string " ", P.string "\t", P.string "\n", P.string "\r"]
-    return JsonTokenWhitespace
-
-  parseJsonTokenBoolean = true <|> false
-    where true  = P.string "true"   >> return (JsonTokenBoolean True)
-          false = P.string "false"  >> return (JsonTokenBoolean False)
-
-instance ParseJson BS.ByteString BS.ByteString Double where
-  parseJsonTokenBraceL    = P.string "{" >> return JsonTokenBraceL
-  parseJsonTokenBraceR    = P.string "}" >> return JsonTokenBraceR
-  parseJsonTokenBracketL  = P.string "[" >> return JsonTokenBracketL
-  parseJsonTokenBracketR  = P.string "]" >> return JsonTokenBracketR
-  parseJsonTokenComma     = P.string "," >> return JsonTokenComma
-  parseJsonTokenColon     = P.string ":" >> return JsonTokenColon
-  parseJsonTokenNull      = P.string "null" >> return JsonTokenNull
-  parseJsonTokenDouble    = JsonTokenNumber <$> P.rational
-
-  parseJsonTokenString = do
-    _ <- P.string "\""
-    value <- many (verbatimChar <|> escapedChar <|> escapedCode)
-    _ <- P.string "\""
-    return $ JsonTokenString $ BS.pack value
-    where
-      word :: Word8 -> T.Parser BS.ByteString Word8
-      word w = P.satisfy (== w)
-      verbatimChar :: T.Parser BS.ByteString Word8
-      verbatimChar  = P.satisfy (\w -> w /= _quotedbl && w /= _backslash) -- <?> "invalid string character"
-      escapedChar :: T.Parser BS.ByteString Word8
-      escapedChar   = do
-        _ <- P.string "\\"
-        (   word _quotedbl    >> return _quotedbl       ) <|>
-          ( word _b           >> return 0x08            ) <|>
-          ( word _n           >> return _lf             ) <|>
-          ( word _f           >> return _np             ) <|>
-          ( word _r           >> return _cr             ) <|>
-          ( word _t           >> return _tab            ) <|>
-          ( word _backslash   >> return _backslash      ) <|>
-          ( word _quotesingle >> return _quotesingle    ) <|>
-          ( word _slash       >> return _slash          )
-      escapedCode :: T.Parser BS.ByteString Word8
-      escapedCode   = do
-        _ <- P.string "\\u"
-        a <- hexDigit
-        b <- hexDigit
-        c <- hexDigit
-        d <- hexDigit
-        return $ fromIntegral $ a `shift` 24 .|. b `shift` 16 .|. c `shift` 8 .|. d
-
-  parseJsonTokenWhitespace = do
-    _ <- AC.many1' $ BC.choice [P.string " ", P.string "\t", P.string "\n", P.string "\r"]
-    return JsonTokenWhitespace
-
-  parseJsonTokenBoolean = true <|> false
-    where
-      true  = P.string "true"   >> return (JsonTokenBoolean True)
-      false = P.string "false"  >> return (JsonTokenBoolean False)
diff --git a/src/HaskellWorks/Data/Json/Internal/CharLike.hs b/src/HaskellWorks/Data/Json/Internal/CharLike.hs
--- a/src/HaskellWorks/Data/Json/Internal/CharLike.hs
+++ b/src/HaskellWorks/Data/Json/Internal/CharLike.hs
@@ -2,7 +2,7 @@
 
 import Data.Word
 import Data.Word8
-import HaskellWorks.Data.Json.Internal.Word8
+import HaskellWorks.Data.Json.Standard.Cursor.Internal.Word8
 
 class JsonCharLike c where
   isLeadingDigit2 :: c -> Bool
diff --git a/src/HaskellWorks/Data/Json/Internal/Doc.hs b/src/HaskellWorks/Data/Json/Internal/Doc.hs
--- a/src/HaskellWorks/Data/Json/Internal/Doc.hs
+++ b/src/HaskellWorks/Data/Json/Internal/Doc.hs
@@ -1,11 +1,27 @@
 module HaskellWorks.Data.Json.Internal.Doc
-  ( hEncloseSep
+  ( hEncloseSep,
+    text,
+    red,
+    dullgreen,
+    cyan,
   ) where
 
-import Text.PrettyPrint.ANSI.Leijen
+import Prettyprinter
 
-hEncloseSep :: Doc -> Doc -> Doc -> [Doc] -> Doc
+hEncloseSep :: Doc a -> Doc a -> Doc a -> [Doc a] -> Doc a
 hEncloseSep l r s ds = case ds of
   []  -> l <> r
   [d] -> l <> d <> r
   _   -> hcat (zipWith (<>) (l : repeat s) ds) <> r
+
+text :: String -> Doc a
+text = pretty
+
+red :: Doc a -> Doc a
+red = id
+
+dullgreen :: Doc a -> Doc a
+dullgreen = id
+
+cyan :: Doc a -> Doc a
+cyan = id
diff --git a/src/HaskellWorks/Data/Json/Internal/Index.hs b/src/HaskellWorks/Data/Json/Internal/Index.hs
--- a/src/HaskellWorks/Data/Json/Internal/Index.hs
+++ b/src/HaskellWorks/Data/Json/Internal/Index.hs
@@ -1,12 +1,27 @@
+{-# LANGUAGE BangPatterns      #-}
 {-# LANGUAGE FlexibleContexts  #-}
 {-# LANGUAGE FlexibleInstances #-}
 
 module HaskellWorks.Data.Json.Internal.Index where
 
+import Control.Arrow
+import Control.Monad
+import HaskellWorks.Data.Bits.BitWise
+import HaskellWorks.Data.Drop
 import HaskellWorks.Data.Json.DecodeError
-import Prelude                            hiding (drop)
+import HaskellWorks.Data.Json.Internal.CharLike
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Positioning
+import HaskellWorks.Data.RankSelect.Base.Rank0
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import HaskellWorks.Data.TreeCursor
+import HaskellWorks.Data.Uncons
+import Prelude                                        hiding (drop)
 
-import qualified Data.ByteString as BS
+import qualified Data.ByteString                  as BS
+import qualified Data.List                        as L
+import qualified HaskellWorks.Data.BalancedParens as BP
 
 data JsonIndex
   = JsonIndexString BS.ByteString
@@ -19,3 +34,26 @@
 
 class JsonIndexAt a where
   jsonIndexAt :: a -> Either DecodeError JsonIndex
+
+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonIndexAt (GenericCursor BS.ByteString v w) where
+  jsonIndexAt k = case uncons remainder of
+    Just (!c, _) | isLeadingDigit2 c -> Right (JsonIndexNumber  remainder)
+    Just (!c, _) | isQuotDbl c       -> Right (JsonIndexString  remainder)
+    Just (!c, _) | isChar_t c        -> Right (JsonIndexBool    True)
+    Just (!c, _) | isChar_f c        -> Right (JsonIndexBool    False)
+    Just (!c, _) | isChar_n c        -> Right  JsonIndexNull
+    Just (!c, _) | isBraceLeft c     -> JsonIndexObject <$> mapValuesFrom   (firstChild k)
+    Just (!c, _) | isBracketLeft c   -> JsonIndexArray  <$> arrayValuesFrom (firstChild k)
+    Just _                           -> Left (DecodeError "Invalid Json Type")
+    Nothing                          -> Left (DecodeError "End of data"      )
+    where ik                = interests k
+          bpk               = balancedParens k
+          p                 = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
+          remainder         = drop (toCount p) (cursorText k)
+          arrayValuesFrom j = sequence (L.unfoldr (fmap (jsonIndexAt &&& nextSibling)) j)
+          mapValuesFrom j   = (pairwise >=> asField) <$> arrayValuesFrom j
+          pairwise (a:b:rs) = (a, b) : pairwise rs
+          pairwise _        = []
+          asField (a, b)    = case a of
+                                JsonIndexString s -> [(s, b)]
+                                _                 -> []
diff --git a/src/HaskellWorks/Data/Json/Internal/PartialIndex.hs b/src/HaskellWorks/Data/Json/Internal/PartialIndex.hs
--- a/src/HaskellWorks/Data/Json/Internal/PartialIndex.hs
+++ b/src/HaskellWorks/Data/Json/Internal/PartialIndex.hs
@@ -1,7 +1,33 @@
+{-# LANGUAGE BangPatterns          #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE InstanceSigs          #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
 module HaskellWorks.Data.Json.Internal.PartialIndex where
 
-import qualified Data.ByteString as BS
+import Control.Arrow
+import Control.Monad
+import Data.String
+import HaskellWorks.Data.Bits.BitWise
+import HaskellWorks.Data.Drop
+import HaskellWorks.Data.Json.Internal.CharLike
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Positioning
+import HaskellWorks.Data.RankSelect.Base.Rank0
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import HaskellWorks.Data.TreeCursor
+import HaskellWorks.Data.Uncons
+import Prelude                                        hiding (drop)
 
+import qualified Data.ByteString                  as BS
+import qualified Data.List                        as L
+import qualified HaskellWorks.Data.BalancedParens as BP
+
 data JsonPartialIndex
   = JsonPartialIndexString BS.ByteString
   | JsonPartialIndexNumber BS.ByteString
@@ -14,3 +40,28 @@
 
 class JsonPartialIndexAt a where
   jsonPartialIndexAt :: a -> JsonPartialIndex
+
+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonPartialIndexAt (GenericCursor BS.ByteString v w) where
+  jsonPartialIndexAt k = case uncons remainder of
+    Just (!c, _) | isLeadingDigit2 c -> JsonPartialIndexNumber  remainder
+    Just (!c, _) | isQuotDbl c       -> JsonPartialIndexString  remainder
+    Just (!c, _) | isChar_t c        -> JsonPartialIndexBool    True
+    Just (!c, _) | isChar_f c        -> JsonPartialIndexBool    False
+    Just (!c, _) | isChar_n c        -> JsonPartialIndexNull
+    Just (!c, _) | isBraceLeft c     -> JsonPartialIndexObject (mapValuesFrom   (firstChild k))
+    Just (!c, _) | isBracketLeft c   -> JsonPartialIndexArray  (arrayValuesFrom (firstChild k))
+    Just _                           -> JsonPartialIndexError "Invalid Json Type"
+    Nothing                          -> JsonPartialIndexError "End of data"
+    where ik                = interests k
+          bpk               = balancedParens k
+          p                 = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
+          remainder         = drop (toCount p) (cursorText k)
+          arrayValuesFrom :: Maybe (GenericCursor BS.ByteString v w) -> [JsonPartialIndex]
+          arrayValuesFrom = L.unfoldr (fmap (jsonPartialIndexAt &&& nextSibling))
+          mapValuesFrom j   = pairwise (arrayValuesFrom j) >>= asField
+          pairwise (a:b:rs) = (a, b) : pairwise rs
+          pairwise _        = []
+          asField (a, b)    = case a of
+                                JsonPartialIndexString s -> [(s, b)]
+                                _                        -> []
+
diff --git a/src/HaskellWorks/Data/Json/Internal/Slurp.hs b/src/HaskellWorks/Data/Json/Internal/Slurp.hs
--- a/src/HaskellWorks/Data/Json/Internal/Slurp.hs
+++ b/src/HaskellWorks/Data/Json/Internal/Slurp.hs
@@ -1,16 +1,21 @@
 {-# LANGUAGE BangPatterns #-}
 
-module HaskellWorks.Data.Json.Internal.Slurp where
+module HaskellWorks.Data.Json.Internal.Slurp
+  ( JsonState(..)
+  , slurpText
+  , slurpNumber
+  ) where
 
-import Data.String
+import Data.Text
 import Data.Word
 import Data.Word8
-import HaskellWorks.Data.Json.Internal.Word8
-import Prelude                               hiding (drop)
+import HaskellWorks.Data.Json.Standard.Cursor.Internal.Word8
+import Prelude                                               hiding (drop)
 
-import qualified Data.ByteString       as BS
-import qualified Data.ByteString.Char8 as BSC
-import qualified Data.List             as L
+import qualified Data.Aeson.Parser.Internal  as AP
+import qualified Data.Attoparsec.ByteString  as PBS
+import qualified Data.ByteString             as BS
+import qualified Data.Text                   as T
 
 data JsonState
   = Escaped
@@ -19,23 +24,29 @@
   | InNumber
   | InIdent
 
-slurpString :: BS.ByteString -> String
-slurpString bs = L.unfoldr genString (InJson, BSC.unpack bs)
-  where genString :: (JsonState, String) -> Maybe (Char, (JsonState, String))
-        genString (InJson, ds) = case ds of
-          (e:es) | e == '"' -> genString  (InString , es)
-          (_:es)            -> genString  (InJson   , es)
-          _                 -> Nothing
-        genString (InString, ds) = case ds of
-          (e:es) | e == '\\' -> genString  (Escaped  , es)
-          (e:_ ) | e == '"'  -> Nothing
-          (e:es)             -> Just (e,   (InString , es))
-          _                  -> Nothing
-        genString (Escaped, ds) = case ds of
-          (_:es) -> Just ('.', (InString , es))
-          _      -> Nothing
-        genString (_, _) = Nothing
+-- | Slurp a JSON string
+--
+-- Examples:
+--
+-- >>> :set -XOverloadedStrings
+-- >>> slurpText "\"Hello\""
+-- Right "Hello"
+-- >>> slurpText "123"
+-- Left "34: Failed reading: satisfy"
+slurpText :: BS.ByteString -> Either Text Text
+slurpText bs = case PBS.parseOnly AP.jstring bs of
+  Right t -> Right t
+  Left e  -> Left (T.pack e)
 
+-- | Slurp a JSON number
+--
+-- Examples:
+--
+-- >>> :set -XOverloadedStrings
+-- >>> slurpNumber "123, true"
+-- "123"
+-- >>> slurpNumber "\"Hello\""
+-- "\"Hello\""
 slurpNumber :: BS.ByteString -> BS.ByteString
 slurpNumber bs = let (!cs, _) = BS.unfoldrN (BS.length bs) genNumber (InJson, bs) in cs
     where genNumber :: (JsonState, BS.ByteString) -> Maybe (Word8, (JsonState, BS.ByteString))
diff --git a/src/HaskellWorks/Data/Json/Internal/Standard/Cursor/Token.hs b/src/HaskellWorks/Data/Json/Internal/Standard/Cursor/Token.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Json/Internal/Standard/Cursor/Token.hs
@@ -0,0 +1,24 @@
+
+module HaskellWorks.Data.Json.Internal.Standard.Cursor.Token
+  ( jsonTokenAt
+  ) where
+
+import Data.ByteString.Internal                                as BSI
+import HaskellWorks.Data.Bits.BitWise
+import HaskellWorks.Data.Drop
+import HaskellWorks.Data.Json.Internal.Standard.Token.Tokenize
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Positioning
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import Prelude                                                 hiding (drop)
+
+import qualified Data.Attoparsec.ByteString.Char8 as ABC
+
+jsonTokenAt :: (Rank1 w, Select1 v, TestBit w) => GenericCursor ByteString v w -> Maybe (JsonToken String Double)
+jsonTokenAt k = if balancedParens k .?. lastPositionOf (cursorRank k)
+  then case ABC.parse parseJsonToken (drop (toCount (jsonCursorPos k)) (cursorText k)) of
+    ABC.Fail    {}  -> error "Failed to parse token in cursor"
+    ABC.Partial _   -> error "Failed to parse token in cursor"
+    ABC.Done    _ r -> Just r
+  else Nothing
diff --git a/src/HaskellWorks/Data/Json/Internal/Standard/Token/Tokenize.hs b/src/HaskellWorks/Data/Json/Internal/Standard/Token/Tokenize.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Json/Internal/Standard/Token/Tokenize.hs
@@ -0,0 +1,166 @@
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
+
+module HaskellWorks.Data.Json.Internal.Standard.Token.Tokenize
+    ( IsChar(..)
+    , JsonToken(..)
+    , ParseJson(..)
+    ) where
+
+import Control.Applicative
+import Data.Bits
+import Data.Char
+import Data.Word
+import Data.Word8
+import HaskellWorks.Data.Char.IsChar
+import HaskellWorks.Data.Json.Internal.Token.Types
+import HaskellWorks.Data.Parser                    ((<?>))
+
+import qualified Data.Attoparsec.ByteString.Char8 as BC
+import qualified Data.Attoparsec.Combinator       as AC
+import qualified Data.Attoparsec.Types            as T
+import qualified Data.ByteString                  as BS
+import qualified HaskellWorks.Data.Parser         as P
+
+{- HLINT ignore "Reduce duplication" -}
+
+hexDigitNumeric :: P.Parser t u => T.Parser t Int
+hexDigitNumeric = do
+  c <- P.satisfyChar (\c -> '0' <= c && c <= '9')
+  return $ ord c - ord '0'
+
+hexDigitAlphaLower :: P.Parser t u => T.Parser t Int
+hexDigitAlphaLower = do
+  c <- P.satisfyChar (\c -> 'a' <= c && c <= 'z')
+  return $ ord c - ord 'a' + 10
+
+hexDigitAlphaUpper :: P.Parser t u => T.Parser t Int
+hexDigitAlphaUpper = do
+  c <- P.satisfyChar (\c -> 'A' <= c && c <= 'Z')
+  return $ ord c - ord 'A' + 10
+
+hexDigit :: P.Parser t u => T.Parser t Int
+hexDigit = hexDigitNumeric <|> hexDigitAlphaLower <|> hexDigitAlphaUpper
+
+class ParseJson t s d where
+  parseJsonTokenString :: T.Parser t (JsonToken s d)
+  parseJsonToken :: T.Parser t (JsonToken s d)
+  parseJsonTokenBraceL :: T.Parser t (JsonToken s d)
+  parseJsonTokenBraceR :: T.Parser t (JsonToken s d)
+  parseJsonTokenBracketL :: T.Parser t (JsonToken s d)
+  parseJsonTokenBracketR :: T.Parser t (JsonToken s d)
+  parseJsonTokenComma :: T.Parser t (JsonToken s d)
+  parseJsonTokenColon :: T.Parser t (JsonToken s d)
+  parseJsonTokenWhitespace :: T.Parser t (JsonToken s d)
+  parseJsonTokenNull :: T.Parser t (JsonToken s d)
+  parseJsonTokenBoolean :: T.Parser t (JsonToken s d)
+  parseJsonTokenDouble :: T.Parser t (JsonToken s d)
+
+  parseJsonToken =
+    parseJsonTokenString     <|>
+    parseJsonTokenBraceL     <|>
+    parseJsonTokenBraceR     <|>
+    parseJsonTokenBracketL   <|>
+    parseJsonTokenBracketR   <|>
+    parseJsonTokenComma      <|>
+    parseJsonTokenColon      <|>
+    parseJsonTokenWhitespace <|>
+    parseJsonTokenNull       <|>
+    parseJsonTokenBoolean    <|>
+    parseJsonTokenDouble
+
+instance ParseJson BS.ByteString String Double where
+  parseJsonTokenBraceL    = P.string "{" >> return JsonTokenBraceL
+  parseJsonTokenBraceR    = P.string "}" >> return JsonTokenBraceR
+  parseJsonTokenBracketL  = P.string "[" >> return JsonTokenBracketL
+  parseJsonTokenBracketR  = P.string "]" >> return JsonTokenBracketR
+  parseJsonTokenComma     = P.string "," >> return JsonTokenComma
+  parseJsonTokenColon     = P.string ":" >> return JsonTokenColon
+  parseJsonTokenNull      = P.string "null" >> return JsonTokenNull
+  parseJsonTokenDouble    = JsonTokenNumber <$> P.rational
+
+  parseJsonTokenString = do
+    _ <- P.string "\""
+    value <- many (verbatimChar <|> escapedChar <|> escapedCode)
+    _ <- P.string "\""
+    return $ JsonTokenString value
+    where
+      verbatimChar  = P.satisfyChar (BC.notInClass "\"\\") <?> "invalid string character"
+      escapedChar   = do
+        _ <- P.string "\\"
+        (   P.char '"'  >> return '"'  ) <|>
+          ( P.char 'b'  >> return '\b' ) <|>
+          ( P.char 'n'  >> return '\n' ) <|>
+          ( P.char 'f'  >> return '\f' ) <|>
+          ( P.char 'r'  >> return '\r' ) <|>
+          ( P.char 't'  >> return '\t' ) <|>
+          ( P.char '\\' >> return '\\' ) <|>
+          ( P.char '\'' >> return '\'' ) <|>
+          ( P.char '/'  >> return '/'  )
+      escapedCode   = do
+        _ <- P.string "\\u"
+        a <- hexDigit
+        b <- hexDigit
+        c <- hexDigit
+        d <- hexDigit
+        return $ chr $ a `shift` 24 .|. b `shift` 16 .|. c `shift` 8 .|. d
+
+  parseJsonTokenWhitespace = do
+    _ <- AC.many1' $ BC.choice [P.string " ", P.string "\t", P.string "\n", P.string "\r"]
+    return JsonTokenWhitespace
+
+  parseJsonTokenBoolean = true <|> false
+    where true  = P.string "true"   >> return (JsonTokenBoolean True)
+          false = P.string "false"  >> return (JsonTokenBoolean False)
+
+instance ParseJson BS.ByteString BS.ByteString Double where
+  parseJsonTokenBraceL    = P.string "{" >> return JsonTokenBraceL
+  parseJsonTokenBraceR    = P.string "}" >> return JsonTokenBraceR
+  parseJsonTokenBracketL  = P.string "[" >> return JsonTokenBracketL
+  parseJsonTokenBracketR  = P.string "]" >> return JsonTokenBracketR
+  parseJsonTokenComma     = P.string "," >> return JsonTokenComma
+  parseJsonTokenColon     = P.string ":" >> return JsonTokenColon
+  parseJsonTokenNull      = P.string "null" >> return JsonTokenNull
+  parseJsonTokenDouble    = JsonTokenNumber <$> P.rational
+
+  parseJsonTokenString = do
+    _ <- P.string "\""
+    value <- many (verbatimChar <|> escapedChar <|> escapedCode)
+    _ <- P.string "\""
+    return $ JsonTokenString $ BS.pack value
+    where
+      word :: Word8 -> T.Parser BS.ByteString Word8
+      word w = P.satisfy (== w)
+      verbatimChar :: T.Parser BS.ByteString Word8
+      verbatimChar  = P.satisfy (\w -> w /= _quotedbl && w /= _backslash) -- <?> "invalid string character"
+      escapedChar :: T.Parser BS.ByteString Word8
+      escapedChar   = do
+        _ <- P.string "\\"
+        (   word _quotedbl    >> return _quotedbl       ) <|>
+          ( word _b           >> return 0x08            ) <|>
+          ( word _n           >> return _lf             ) <|>
+          ( word _f           >> return _np             ) <|>
+          ( word _r           >> return _cr             ) <|>
+          ( word _t           >> return _tab            ) <|>
+          ( word _backslash   >> return _backslash      ) <|>
+          ( word _quotesingle >> return _quotesingle    ) <|>
+          ( word _slash       >> return _slash          )
+      escapedCode :: T.Parser BS.ByteString Word8
+      escapedCode   = do
+        _ <- P.string "\\u"
+        a <- hexDigit
+        b <- hexDigit
+        c <- hexDigit
+        d <- hexDigit
+        return $ fromIntegral $ a `shift` 24 .|. b `shift` 16 .|. c `shift` 8 .|. d
+
+  parseJsonTokenWhitespace = do
+    _ <- AC.many1' $ BC.choice [P.string " ", P.string "\t", P.string "\n", P.string "\r"]
+    return JsonTokenWhitespace
+
+  parseJsonTokenBoolean = true <|> false
+    where
+      true  = P.string "true"   >> return (JsonTokenBoolean True)
+      false = P.string "false"  >> return (JsonTokenBoolean False)
diff --git a/src/HaskellWorks/Data/Json/Internal/Token.hs b/src/HaskellWorks/Data/Json/Internal/Token.hs
--- a/src/HaskellWorks/Data/Json/Internal/Token.hs
+++ b/src/HaskellWorks/Data/Json/Internal/Token.hs
@@ -2,4 +2,4 @@
   ( module X
   ) where
 
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Token.Tokenize as X
+import HaskellWorks.Data.Json.Internal.Standard.Token.Tokenize as X
diff --git a/src/HaskellWorks/Data/Json/Internal/Value.hs b/src/HaskellWorks/Data/Json/Internal/Value.hs
--- a/src/HaskellWorks/Data/Json/Internal/Value.hs
+++ b/src/HaskellWorks/Data/Json/Internal/Value.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
@@ -59,4 +58,7 @@
       b <- parseHexDigit
       c <- parseHexDigit
       d <- parseHexDigit
-      return $ chr $ a `shift` 24 .|. b `shift` 16 .|. c `shift` 8 .|. d
+      let res =  a `shift` 12 .|. b `shift` 8 .|. c `shift` 4 .|. d
+      return $ if res <= 0x10FFFF
+                then chr res
+                else '�'
diff --git a/src/HaskellWorks/Data/Json/Internal/Word64.hs b/src/HaskellWorks/Data/Json/Internal/Word64.hs
--- a/src/HaskellWorks/Data/Json/Internal/Word64.hs
+++ b/src/HaskellWorks/Data/Json/Internal/Word64.hs
@@ -2,7 +2,7 @@
 
 import Data.Word
 
-import qualified HaskellWorks.Data.Json.Internal.Word8 as W8
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Internal.Word8 as W8
 
 doubleQuote :: Word64
 doubleQuote = 0x0101010101010101 * fromIntegral W8.doubleQuote
diff --git a/src/HaskellWorks/Data/Json/Internal/Word8.hs b/src/HaskellWorks/Data/Json/Internal/Word8.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Internal/Word8.hs
+++ /dev/null
@@ -1,72 +0,0 @@
-module HaskellWorks.Data.Json.Internal.Word8 where
-
-import Data.Word
-import Data.Word8 hiding (isDigit)
-
-import qualified Data.Char as C
-
-isLeadingDigit :: Word8 -> Bool
-isLeadingDigit w = w == _hyphen || (w >= _0 && w <= _9)
-
-isTrailingDigit :: Word8 -> Bool
-isTrailingDigit w = w == _plus || w == _hyphen || (w >= _0 && w <= _9) || w == _period || w == _E || w == _e
-
-isAlphabetic :: Word8 -> Bool
-isAlphabetic w = (w >= _A && w <= _Z) || (w >= _a && w <= _z)
-
-isDigit :: Word8 -> Bool
-isDigit w = w >= _0 && w <= _9
-
-wIsJsonNumberDigit :: Word8 -> Bool
-wIsJsonNumberDigit w = (w >= _0 && w <= _9) || w == _hyphen
-
-doubleQuote :: Word8
-doubleQuote = fromIntegral (C.ord '"')
-
-backSlash :: Word8
-backSlash = fromIntegral (C.ord '\\')
-
-openBrace :: Word8
-openBrace = fromIntegral (C.ord '{')
-
-closeBrace :: Word8
-closeBrace = fromIntegral (C.ord '}')
-
-openBracket :: Word8
-openBracket = fromIntegral (C.ord '[')
-
-closeBracket :: Word8
-closeBracket = fromIntegral (C.ord ']')
-
-comma :: Word8
-comma = fromIntegral (C.ord ',')
-
-colon :: Word8
-colon = fromIntegral (C.ord ':')
-
-isPeriod :: Word8 -> Bool
-isPeriod w = w == 46
-
-isMinus :: Word8 -> Bool
-isMinus w = w == 45
-
-isPlus :: Word8 -> Bool
-isPlus w = w == 43
-
-isValueChar :: Word8 -> Bool
-isValueChar c = isAlphabetic c || isDigit c || isPeriod c || isMinus c || isPlus c
-
-isOpen :: Word8 -> Bool
-isOpen c = c == openBracket || c == openBrace
-
-isClose :: Word8 -> Bool
-isClose c = c == closeBracket || c == closeBrace
-
-isDelim :: Word8 -> Bool
-isDelim c = c == comma || c == colon
-
-isDoubleQuote :: Word8 -> Bool
-isDoubleQuote c = c == doubleQuote
-
-isBackSlash :: Word8 -> Bool
-isBackSlash c = c == backSlash
diff --git a/src/HaskellWorks/Data/Json/LightJson.hs b/src/HaskellWorks/Data/Json/LightJson.hs
--- a/src/HaskellWorks/Data/Json/LightJson.hs
+++ b/src/HaskellWorks/Data/Json/LightJson.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE BangPatterns          #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE InstanceSigs          #-}
@@ -8,37 +9,58 @@
 module HaskellWorks.Data.Json.LightJson where
 
 import Control.Arrow
+import Control.Monad
 import Data.String
+import Data.Text                                      (Text)
+import HaskellWorks.Data.Bits.BitWise
+import HaskellWorks.Data.Drop
+import HaskellWorks.Data.Json.Internal.CharLike
 import HaskellWorks.Data.Json.Internal.Doc
+import HaskellWorks.Data.Json.Internal.Slurp
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
 import HaskellWorks.Data.MQuery
 import HaskellWorks.Data.MQuery.AtLeastSize
 import HaskellWorks.Data.MQuery.Entry
 import HaskellWorks.Data.MQuery.Micro
 import HaskellWorks.Data.MQuery.Mini
 import HaskellWorks.Data.MQuery.Row
-import Prelude                              hiding (drop)
-import Text.PrettyPrint.ANSI.Leijen
+import HaskellWorks.Data.Positioning
+import HaskellWorks.Data.RankSelect.Base.Rank0
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import HaskellWorks.Data.TreeCursor
+import HaskellWorks.Data.Uncons
+import Prelude                                        hiding (drop)
+import Prettyprinter
 
-import qualified Data.ByteString as BS
+import qualified Data.ByteString                      as BS
+import qualified Data.ByteString.Unsafe               as BSU
+import qualified Data.List                            as L
+import qualified Data.Text                            as T
+import qualified HaskellWorks.Data.BalancedParens     as BP
+import qualified HaskellWorks.Data.Json.Simple.Cursor as JSC
 
 data LightJson c
-  = LightJsonString String
+  = LightJsonString Text
   | LightJsonNumber BS.ByteString
-  | LightJsonObject [(String, c)]
+  | LightJsonObject [(Text, c)]
   | LightJsonArray [c]
   | LightJsonBool Bool
   | LightJsonNull
-  | LightJsonError String
+  | LightJsonError Text
   deriving Show
 
-instance Eq (LightJson c) where
+instance LightJsonAt c => Eq (LightJson c) where
   (==) (LightJsonString a) (LightJsonString b) = a == b
   (==) (LightJsonNumber a) (LightJsonNumber b) = a == b
   (==) (LightJsonBool   a) (LightJsonBool   b) = a == b
+  (==) (LightJsonObject a) (LightJsonObject b) = fmap (fmap lightJsonAt) a == fmap (fmap lightJsonAt) b
+  (==) (LightJsonArray  a) (LightJsonArray  b) = fmap lightJsonAt a == fmap lightJsonAt b
   (==)  LightJsonNull       LightJsonNull      = True
+  (==) (LightJsonError  a) (LightJsonError  b) = a == b
   (==)  _                   _                  = False
 
-data LightJsonField c = LightJsonField String (LightJson c)
+data LightJsonField c = LightJsonField Text (LightJson c)
 
 class LightJsonAt a where
   lightJsonAt :: a -> LightJson a
@@ -55,8 +77,8 @@
     LightJsonArray vs   -> hEncloseSep (text "[") (text "]") (text ",") ((pretty . lightJsonAt) `map` vs)
     LightJsonBool w     -> red (text (show w))
     LightJsonNull       -> text "null"
-    LightJsonError s    -> text "<error " <> text s <> text ">"
-    where toLightJsonField :: (String, LightJson c) -> LightJsonField c
+    LightJsonError s    -> text "<error " <> text (T.unpack s) <> text ">"
+    where toLightJsonField :: (Text, LightJson c) -> LightJsonField c
           toLightJsonField (k, v) = LightJsonField k v
 
 instance Pretty (Micro (LightJson c)) where
@@ -68,16 +90,18 @@
   pretty (Micro (LightJsonArray _  )) = text "[..]"
   pretty (Micro (LightJsonBool w   )) = red (text (show w))
   pretty (Micro  LightJsonNull      ) = text "null"
-  pretty (Micro (LightJsonError s  )) = text "<error " <> text s <> text ">"
+  pretty (Micro (LightJsonError s  )) = text "<error " <> text (T.unpack s) <> text ">"
 
 instance Pretty (Micro (String, LightJson c)) where
   pretty (Micro (fieldName, jpv)) = red (text (show fieldName)) <> text ": " <> pretty (Micro jpv)
 
+instance Pretty (Micro (Text, LightJson c)) where
+  pretty (Micro (fieldName, jpv)) = red (text (show fieldName)) <> text ": " <> pretty (Micro jpv)
+
 instance LightJsonAt c => Pretty (Mini (LightJson c)) where
   pretty mjpv = case mjpv of
     Mini (LightJsonString s   ) -> dullgreen  (text (show s))
     Mini (LightJsonNumber n   ) -> cyan       (text (show n))
-    Mini (LightJsonObject []  ) -> text "{}"
     Mini (LightJsonObject kvs ) -> case kvs of
       (_:_:_:_:_:_:_:_:_:_:_:_:_) -> text "{" <> prettyKvs (map (second lightJsonAt) kvs) <> text ", ..}"
       []                          -> text "{}"
@@ -88,13 +112,57 @@
     Mini (LightJsonArray _    )                       -> text "[]"
     Mini (LightJsonBool w     ) -> red (text (show w))
     Mini  LightJsonNull         -> text "null"
-    Mini (LightJsonError s    ) -> text "<error " <> text s <> text ">"
+    Mini (LightJsonError s    ) -> text "<error " <> text (T.unpack s) <> text ">"
 
 instance LightJsonAt c => Pretty (Mini (String, LightJson c)) where
   pretty (Mini (fieldName, jpv)) = text (show fieldName) <> text ": " <> pretty (Mini jpv)
 
+instance LightJsonAt c => Pretty (Mini (Text, LightJson c)) where
+  pretty (Mini (fieldName, jpv)) = text (show fieldName) <> text ": " <> pretty (Mini jpv)
+
 instance LightJsonAt c => Pretty (MQuery (LightJson c)) where
   pretty = pretty . Row 120 . mQuery
 
 instance LightJsonAt c => Pretty (MQuery (Entry String (LightJson c))) where
   pretty (MQuery das) = pretty (Row 120 das)
+
+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => LightJsonAt (GenericCursor BS.ByteString v w) where
+  lightJsonAt k = case uncons remainder of
+    Just (!c, _) | isLeadingDigit2 c -> LightJsonNumber  (slurpNumber remainder)
+    Just (!c, _) | isQuotDbl c       -> either LightJsonError LightJsonString (slurpText remainder)
+    Just (!c, _) | isChar_t c        -> LightJsonBool    True
+    Just (!c, _) | isChar_f c        -> LightJsonBool    False
+    Just (!c, _) | isChar_n c        -> LightJsonNull
+    Just (!c, _) | isBraceLeft c     -> LightJsonObject (mapValuesFrom   (firstChild k))
+    Just (!c, _) | isBracketLeft c   -> LightJsonArray  (arrayValuesFrom (firstChild k))
+    Just _                           -> LightJsonError "Invalid Json Type"
+    Nothing                          -> LightJsonError "End of data"
+    where ik                = interests k
+          bpk               = balancedParens k
+          p                 = lastPositionOf (select1 ik (rank1 bpk (cursorRank k)))
+          remainder         = drop (toCount p) (cursorText k)
+          arrayValuesFrom   = L.unfoldr (fmap (id &&& nextSibling))
+          mapValuesFrom j   = pairwise (arrayValuesFrom j) >>= asField
+          pairwise (a:b:rs) = (a, b) : pairwise rs
+          pairwise _        = []
+          asField (a, b)    = case lightJsonAt a of
+                                LightJsonString s -> [(s, b)]
+                                _                 -> []
+
+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => LightJsonAt (JSC.JsonCursor BS.ByteString v w) where
+  lightJsonAt k = if kra `mod` 2 == 1
+    then let i = fromIntegral (kpa - 1) :: Int in
+      if i < BS.length kt
+        then case BSU.unsafeIndex kt i of
+          91  -> LightJsonArray  []
+          123 -> LightJsonObject []
+          _   -> LightJsonError "Invalid collection character"
+        else LightJsonError "Index out of bounds"
+    else LightJsonError "Unaligned cursor"
+    where kpa   = select1 kib kta + km
+          kib   = JSC.interests k
+          kra   = JSC.cursorRank k
+          ksa   = kra + 1
+          kta   = ksa `div` 2
+          km    = ksa `mod` 2
+          kt    = JSC.cursorText k
diff --git a/src/HaskellWorks/Data/Json/PartialValue.hs b/src/HaskellWorks/Data/Json/PartialValue.hs
--- a/src/HaskellWorks/Data/Json/PartialValue.hs
+++ b/src/HaskellWorks/Data/Json/PartialValue.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
@@ -10,6 +9,7 @@
   , JsonPartialValueAt(..)
   , asInteger
   , asString
+  , asText
   , castAsInteger
   , entry
   , hasKey
@@ -21,37 +21,69 @@
   ) where
 
 import Control.Arrow
+import Data.String
+import Data.Text                                      (Text)
+import HaskellWorks.Data.Bits.BitWise
 import HaskellWorks.Data.Json.Internal.Doc
 import HaskellWorks.Data.Json.Internal.PartialIndex
 import HaskellWorks.Data.Json.Internal.Value
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
 import HaskellWorks.Data.MQuery
 import HaskellWorks.Data.MQuery.AtLeastSize
 import HaskellWorks.Data.MQuery.Entry
 import HaskellWorks.Data.MQuery.Micro
 import HaskellWorks.Data.MQuery.Mini
 import HaskellWorks.Data.MQuery.Row
-import Text.PrettyPrint.ANSI.Leijen
+import HaskellWorks.Data.RankSelect.Base.Rank0
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import Prelude                                        hiding (drop)
+import Prettyprinter
 
 import qualified Data.Attoparsec.ByteString.Char8 as ABC
 import qualified Data.ByteString                  as BS
 import qualified Data.DList                       as DL
+import qualified Data.Text                        as T
+import qualified HaskellWorks.Data.BalancedParens as BP
 
+-- | Partial JSON type.
+--
+-- This data type has an additional 'JsonPartialError' data constructor to indicate parsing
+-- errors.  This allows parsing to be more lazy because parsing errors may now be expressed
+-- anywhere in the parsed document so the parser no longer needs to make a verdict about whether
+-- there are any parsing errors in the entire document.
+--
+-- See 'jsonPartialJsonValueAt' on how to parse JSON text into this datatype.
+--
+-- Although this data type allows for lazier parsing it doesn't allow for sub-trees to be
+-- garbage collected if a reference to an ancestor node is held.  To avoid holding onto
+-- sub-trees that are no longer needed without having to drop references to ancestors use
+-- 'HaskellWorks.Data.Json.LightJson.LightJson' instead.
 data JsonPartialValue
-  = JsonPartialString String
+  = JsonPartialString Text
   | JsonPartialNumber Double
-  | JsonPartialObject [(String, JsonPartialValue)]
+  | JsonPartialObject [(Text, JsonPartialValue)]
   | JsonPartialArray [JsonPartialValue]
   | JsonPartialBool Bool
   | JsonPartialNull
-  | JsonPartialError String
+  | JsonPartialError Text
   deriving (Eq, Show, Ord)
 
 class JsonPartialValueAt a where
+  -- | Get a JSON partial value from another type
+  --
+  -- This function can always "succeed" because the data type it returns allows for the document value
+  -- to contain an arbitrary number of errors.  This means errors can be reported in document nodes
+  -- as parsing occurs lazily.
+  --
+  -- There are garbage collection implementations you may want to consider.  If you would like to be
+  -- able to hold onto ancestor nodes and still be able to garbage collect visited sub-trees, then
+  -- consider using 'HaskellWorks.Data.Json.LightJson.lightJsonAt' instead.
   jsonPartialJsonValueAt :: a -> JsonPartialValue
 
-data JsonPartialField = JsonPartialField String JsonPartialValue
+data JsonPartialField = JsonPartialField Text JsonPartialValue
 
-jsonPartialValueString :: JsonPartialValue -> String
+jsonPartialValueString :: JsonPartialValue -> Text
 jsonPartialValueString pjv = case pjv of
   JsonPartialString s -> s
   _                   -> ""
@@ -59,13 +91,13 @@
 instance JsonPartialValueAt JsonPartialIndex where
   jsonPartialJsonValueAt i = case i of
     JsonPartialIndexString s  -> case ABC.parse parseJsonString s of
-      ABC.Fail    {}  -> JsonPartialError ("Invalid string: '" ++ show (BS.take 20 s) ++ "...'")
+      ABC.Fail    {}  -> JsonPartialError ("Invalid string: '" <> T.pack (show (BS.take 20 s)) <> "...'")
       ABC.Partial _   -> JsonPartialError "Unexpected end of string"
-      ABC.Done    _ r -> JsonPartialString r
+      ABC.Done    _ r -> JsonPartialString (T.pack r) -- TODO optimise
     JsonPartialIndexNumber s  -> case ABC.parse ABC.rational s of
-      ABC.Fail    {}    -> JsonPartialError ("Invalid number: '" ++ show (BS.take 20 s) ++ "...'")
+      ABC.Fail    {}    -> JsonPartialError ("Invalid number: '" <> T.pack (show (BS.take 20 s)) <> "...'")
       ABC.Partial f     -> case f " " of
-        ABC.Fail    {}  -> JsonPartialError ("Invalid number: '" ++ show (BS.take 20 s) ++ "...'")
+        ABC.Fail    {}  -> JsonPartialError ("Invalid number: '" <> T.pack (show (BS.take 20 s)) <> "...'")
         ABC.Partial _   -> JsonPartialError "Unexpected end of number"
         ABC.Done    _ r -> JsonPartialNumber r
       ABC.Done    _ r   -> JsonPartialNumber r
@@ -73,13 +105,13 @@
     JsonPartialIndexArray   es -> JsonPartialArray (map jsonPartialJsonValueAt es)
     JsonPartialIndexBool    v  -> JsonPartialBool v
     JsonPartialIndexNull       -> JsonPartialNull
-    JsonPartialIndexError s    -> JsonPartialError s
+    JsonPartialIndexError s    -> JsonPartialError (T.pack s) -- TODO optimise
     where parseString bs = case ABC.parse parseJsonString bs of
-            ABC.Fail    {}  -> JsonPartialError ("Invalid field: '" ++ show (BS.take 20 bs) ++ "...'")
+            ABC.Fail    {}  -> JsonPartialError ("Invalid field: '" <> T.pack (show (BS.take 20 bs)) <> "...'")
             ABC.Partial _   -> JsonPartialError "Unexpected end of field"
-            ABC.Done    _ s -> JsonPartialString s
+            ABC.Done    _ s -> JsonPartialString (T.pack s) -- TODO optimise
 
-toJsonPartialField :: (String, JsonPartialValue) -> JsonPartialField
+toJsonPartialField :: (Text, JsonPartialValue) -> JsonPartialField
 toJsonPartialField (k, v) = JsonPartialField k v
 
 instance Pretty JsonPartialField where
@@ -94,7 +126,7 @@
     JsonPartialArray vs   -> hEncloseSep (text "[") (text "]") (text ",") (pretty `map` vs)
     JsonPartialBool w     -> red (text (show w))
     JsonPartialNull       -> text "null"
-    JsonPartialError s    -> text "<error " <> text s <> text ">"
+    JsonPartialError s    -> text "<error " <> text (T.unpack s) <> text ">"
 
 instance Pretty (Micro JsonPartialValue) where
   pretty (Micro (JsonPartialString s )) = dullgreen (text (show s))
@@ -105,19 +137,21 @@
   pretty (Micro (JsonPartialArray _  )) = text "[..]"
   pretty (Micro (JsonPartialBool w   )) = red (text (show w))
   pretty (Micro  JsonPartialNull      ) = text "null"
-  pretty (Micro (JsonPartialError s  )) = text "<error " <> text s <> text ">"
+  pretty (Micro (JsonPartialError s  )) = text "<error " <> text (T.unpack s) <> text ">"
 
 instance Pretty (Micro (String, JsonPartialValue)) where
   pretty (Micro (fieldName, jpv)) = red (text (show fieldName)) <> text ": " <> pretty (Micro jpv)
 
+instance Pretty (Micro (Text, JsonPartialValue)) where
+  pretty (Micro (fieldName, jpv)) = red (text (show fieldName)) <> text ": " <> pretty (Micro jpv)
+
 instance Pretty (Mini JsonPartialValue) where
   pretty mjpv = case mjpv of
     Mini (JsonPartialString s   ) -> dullgreen  (text (show s))
     Mini (JsonPartialNumber n   ) -> cyan       (text (show n))
-    Mini (JsonPartialObject []  ) -> text "{}"
     Mini (JsonPartialObject kvs ) -> case kvs of
-      (_:_:_:_:_:_:_:_:_:_:_:_:_) -> text "{" <> prettyKvs kvs <> text ", ..}"
       []                          -> text "{}"
+      (_:_:_:_:_:_:_:_:_:_:_:_:_) -> text "{" <> prettyKvs kvs <> text ", ..}"
       _                           -> text "{" <> prettyKvs kvs <> text "}"
     Mini (JsonPartialArray []   ) -> text "[]"
     Mini (JsonPartialArray vs   ) | vs `atLeastSize` 11 -> text "[" <> nest 2 (prettyVs (Micro `map` take 10 vs)) <> text ", ..]"
@@ -125,18 +159,21 @@
     Mini (JsonPartialArray _    )                       -> text "[]"
     Mini (JsonPartialBool w     ) -> red (text (show w))
     Mini  JsonPartialNull         -> text "null"
-    Mini (JsonPartialError s    ) -> text "<error " <> text s <> text ">"
+    Mini (JsonPartialError s    ) -> text "<error " <> text (T.unpack s) <> text ">"
 
-instance Pretty (Mini (String, JsonPartialValue)) where
+instance Pretty (Mini (Text, JsonPartialValue)) where
   pretty (Mini (fieldName, jpv)) = text (show fieldName) <> text ": " <> pretty (Mini jpv)
 
 instance Pretty (MQuery JsonPartialValue) where
   pretty = pretty . Row 120 . mQuery
 
-instance Pretty (MQuery (Entry String JsonPartialValue)) where
+instance Pretty (MQuery (Entry Text JsonPartialValue)) where
   pretty (MQuery das) = pretty (Row 120 das)
 
-hasKV :: String -> JsonPartialValue -> JsonPartialValue -> MQuery JsonPartialValue
+instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonPartialValueAt (GenericCursor BS.ByteString v w) where
+  jsonPartialJsonValueAt = jsonPartialJsonValueAt . jsonPartialIndexAt
+
+hasKV :: Text -> JsonPartialValue -> JsonPartialValue -> MQuery JsonPartialValue
 hasKV k v (JsonPartialObject xs) = if (k, v) `elem` xs then MQuery (DL.singleton (JsonPartialObject xs)) else MQuery DL.empty
 hasKV _ _  _                     = MQuery DL.empty
 
@@ -145,13 +182,18 @@
   JsonPartialArray es -> MQuery $ DL.fromList es
   _                   -> MQuery   DL.empty
 
-entry :: JsonPartialValue -> MQuery (Entry String JsonPartialValue)
+entry :: JsonPartialValue -> MQuery (Entry Text JsonPartialValue)
 entry jpv = case jpv of
   JsonPartialObject fs -> MQuery $ DL.fromList (uncurry Entry `map` fs)
   _                    -> MQuery   DL.empty
 
 asString :: JsonPartialValue -> MQuery String
 asString jpv = case jpv of
+  JsonPartialString s -> MQuery $ DL.singleton (T.unpack s)
+  _                   -> MQuery   DL.empty
+
+asText :: JsonPartialValue -> MQuery Text
+asText jpv = case jpv of
   JsonPartialString s -> MQuery $ DL.singleton s
   _                   -> MQuery   DL.empty
 
@@ -162,20 +204,20 @@
 
 castAsInteger :: JsonPartialValue -> MQuery Integer
 castAsInteger jpv = case jpv of
-  JsonPartialString n -> MQuery $ DL.singleton (read n)
+  JsonPartialString n -> MQuery $ DL.singleton (read (T.unpack n))
   JsonPartialNumber n -> MQuery $ DL.singleton (floor n)
   _                   -> MQuery   DL.empty
 
-named :: String -> Entry String JsonPartialValue -> MQuery JsonPartialValue
+named :: Text -> Entry Text JsonPartialValue -> MQuery JsonPartialValue
 named fieldName (Entry fieldName' jpv) | fieldName == fieldName'  = MQuery $ DL.singleton jpv
 named _         _                      = MQuery   DL.empty
 
-jsonKeys :: JsonPartialValue -> [String]
+jsonKeys :: JsonPartialValue -> [Text]
 jsonKeys jpv = case jpv of
   JsonPartialObject fs -> fst `map` fs
   _                    -> []
 
-hasKey :: String -> JsonPartialValue -> Bool
+hasKey :: Text -> JsonPartialValue -> Bool
 hasKey fieldName jpv = fieldName `elem` jsonKeys jpv
 
 jsonSize :: JsonPartialValue -> MQuery JsonPartialValue
diff --git a/src/HaskellWorks/Data/Json/Query.hs b/src/HaskellWorks/Data/Json/Query.hs
--- a/src/HaskellWorks/Data/Json/Query.hs
+++ b/src/HaskellWorks/Data/Json/Query.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
@@ -8,7 +7,7 @@
 module HaskellWorks.Data.Json.Query where
 
 import Control.Arrow
-import Data.String
+import Data.Text                        (Text)
 import HaskellWorks.Data.Json.LightJson
 import HaskellWorks.Data.MQuery
 import HaskellWorks.Data.MQuery.Entry
@@ -16,18 +15,19 @@
 
 import qualified Data.Attoparsec.ByteString.Char8 as ABC
 import qualified Data.DList                       as DL
+import qualified Data.Text                        as T
 
 item :: LightJsonAt c => LightJson c -> MQuery (LightJson c)
 item jpv = case jpv of
   LightJsonArray es -> MQuery $ DL.fromList (lightJsonAt `map` es)
   _                 -> MQuery   DL.empty
 
-entry :: LightJsonAt c => LightJson c -> MQuery (Entry String (LightJson c))
+entry :: LightJsonAt c => LightJson c -> MQuery (Entry Text (LightJson c))
 entry jpv = case jpv of
   LightJsonObject fs -> MQuery $ DL.fromList ((uncurry Entry . second lightJsonAt) `map` fs)
   _                  -> MQuery   DL.empty
 
-asString :: LightJson c -> MQuery String
+asString :: LightJson c -> MQuery Text
 asString jpv = case jpv of
   LightJsonString s -> MQuery $ DL.singleton s
   _                 -> MQuery   DL.empty
@@ -50,20 +50,20 @@
 
 castAsInteger :: LightJson c -> MQuery Integer
 castAsInteger jpv = case jpv of
-  LightJsonString n -> MQuery $ DL.singleton (read n)
+  LightJsonString n -> MQuery $ DL.singleton (read (T.unpack n)) -- TODO Optimise
   LightJsonNumber _ -> asInteger jpv
   _                 -> MQuery   DL.empty
 
-named :: String -> Entry String (LightJson c) -> MQuery (LightJson c)
+named :: Text -> Entry Text (LightJson c) -> MQuery (LightJson c)
 named fieldName (Entry fieldName' jpv) | fieldName == fieldName'  = MQuery $ DL.singleton jpv
 named _         _                      = MQuery   DL.empty
 
-jsonKeys :: LightJson c -> [String]
+jsonKeys :: LightJson c -> [Text]
 jsonKeys jpv = case jpv of
   LightJsonObject fs -> fst `map` fs
   _                  -> []
 
-hasKey :: String -> LightJson c -> Bool
+hasKey :: Text -> LightJson c -> Bool
 hasKey fieldName jpv = fieldName `elem` jsonKeys jpv
 
 jsonSize :: LightJson c -> MQuery Integer
diff --git a/src/HaskellWorks/Data/Json/Simple/Value.hs b/src/HaskellWorks/Data/Json/Simple/Value.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Json/Simple/Value.hs
@@ -0,0 +1,42 @@
+module HaskellWorks.Data.Json.Simple.Value where
+
+import Data.Maybe
+import HaskellWorks.Data.Json.Simple.Cursor
+import HaskellWorks.Data.Positioning
+import HaskellWorks.Data.RankSelect.Base.Select1
+import HaskellWorks.Data.RankSelect.CsPoppy
+
+import qualified Data.ByteString                           as BS
+import qualified HaskellWorks.Data.BalancedParens          as BP
+import qualified HaskellWorks.Data.BalancedParens.RangeMin as RM
+
+data JsonValue
+  = JsonValues JsonValues
+  | JsonNull
+  | JsonNumber Double
+  | JsonString String
+  | JsonBoolean Bool
+  deriving (Eq, Show)
+
+data JsonValues
+  = JsonArray  [JsonValue]
+  | JsonObject [(String, JsonValue)]
+  deriving (Eq, Show)
+
+snippetPos :: JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy) -> (Count, Count)
+snippetPos k = (kpa, kpz)
+  where kpa   = select1 kib kta + km
+        kpz   = select1 kib ktz - km
+        kib   = interests k
+        kbp   = balancedParens k
+        kra   = cursorRank k
+        krz   = fromMaybe maxBound (BP.findClose kbp kra)
+        ksa   = kra + 1
+        ksz   = krz + 1
+        kta   = ksa `div` 2
+        ktz   = ksz `div` 2
+        km    = ksa `mod` 2
+
+snippet :: JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy) -> BS.ByteString
+snippet k = let (a, z) = snippetPos k in BS.take (fromIntegral (z - a + 1)) (BS.drop (fromIntegral (a - 1)) kt)
+  where kt    = cursorText k
diff --git a/src/HaskellWorks/Data/Json/Standard/Load/Partial.hs b/src/HaskellWorks/Data/Json/Standard/Load/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Json/Standard/Load/Partial.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module HaskellWorks.Data.Json.Standard.Load.Partial
+  ( loadPartial
+  , loadPartialWithCsPoppyIndex
+  , loadPartialWithIndex
+  ) where
+
+import HaskellWorks.Data.BalancedParens.Simple
+import HaskellWorks.Data.Bits.BitShown
+import HaskellWorks.Data.Json.Internal.PartialIndex
+import HaskellWorks.Data.Json.PartialValue
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Json.Standard.Cursor.Load.Raw
+import HaskellWorks.Data.RankSelect.CsPoppy
+
+loadPartialWithIndex :: String -> IO JsonPartialValue
+loadPartialWithIndex filename = do
+  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
+  let cursor = GenericCursor jsonBS (BitShown jsonIb) (SimpleBalancedParens jsonBp) 1
+  let !jsonResult = jsonPartialJsonValueAt (jsonPartialIndexAt cursor)
+  return jsonResult
+
+loadPartialWithCsPoppyIndex :: String -> IO JsonPartialValue
+loadPartialWithCsPoppyIndex filename = do
+  (jsonBS, jsonIb, jsonBp) <- loadRawWithIndex filename
+  let cursor = GenericCursor jsonBS (makeCsPoppy jsonIb) (SimpleBalancedParens jsonBp) 1
+  let !jsonResult = jsonPartialJsonValueAt (jsonPartialIndexAt cursor)
+  return jsonResult
+
+loadPartial :: String -> IO JsonPartialValue
+loadPartial = loadPartialWithCsPoppyIndex
diff --git a/src/HaskellWorks/Data/Json/Type.hs b/src/HaskellWorks/Data/Json/Type.hs
deleted file mode 100644
--- a/src/HaskellWorks/Data/Json/Type.hs
+++ /dev/null
@@ -1,26 +0,0 @@
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-
-module HaskellWorks.Data.Json.Type
-  ( JsonType(..)
-  , JsonTypeAt(..)
-  ) where
-
-import HaskellWorks.Data.Positioning
-import Prelude                       hiding (drop)
-
-{-# ANN module ("HLint: Reduce duplication" :: String) #-}
-
-data JsonType
-  = JsonTypeArray
-  | JsonTypeBool
-  | JsonTypeNull
-  | JsonTypeNumber
-  | JsonTypeObject
-  | JsonTypeString
-  deriving (Eq, Show)
-
-class JsonTypeAt a where
-  jsonTypeAtPosition :: Position -> a -> Maybe JsonType
-  jsonTypeAt :: a -> Maybe JsonType
diff --git a/src/HaskellWorks/Data/Json/Value.hs b/src/HaskellWorks/Data/Json/Value.hs
--- a/src/HaskellWorks/Data/Json/Value.hs
+++ b/src/HaskellWorks/Data/Json/Value.hs
@@ -1,28 +1,51 @@
 {-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE InstanceSigs          #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 
 module HaskellWorks.Data.Json.Value where
 
+import Data.Text                             (Text)
 import HaskellWorks.Data.Json.DecodeError
 import HaskellWorks.Data.Json.Internal.Index
 import HaskellWorks.Data.Json.Internal.Value
 
 import qualified Data.Attoparsec.ByteString.Char8 as ABC
 import qualified Data.ByteString                  as BS
+import qualified Data.Text                        as T
 
+-- | Traditional JSON type.
+--
+-- This type has the a constructor per JSON data type as is typical for JSON in most libraries.
+--
+-- See 'jsonValueAt' on how to parse JSON text into this datatype.
+--
+-- Although Haskell data types are lazy by default, you will not get a fully lazy data structure
+-- when parsing to this type because there is no way to express parsing errors in this datatype.
+--
+-- For a data type that gives you lazier behaviour, see other alternatives such as
+-- 'HaskellWorks.Data.Json.PartialValue.JsonPartialValue' or 'HaskellWorks.Data.Json.LightJson.LightJson'.
 data JsonValue
-  = JsonString String
+  = JsonString Text
   | JsonNumber Double
-  | JsonObject [(String, JsonValue)]
+  | JsonObject [(Text, JsonValue)]
   | JsonArray [JsonValue]
   | JsonBool Bool
   | JsonNull
   deriving (Eq, Show)
 
 class JsonValueAt a where
+  -- | Get a JSON value from another type
+  --
+  -- The @hw-json@ library does not do full JSON validation for efficiency reasons, but parsing can
+  -- fail if the JSON is malformed.  When parsing fails, then 'Left' will be returned.
+  --
+  -- If 'Right' is returned then that means there are no parsing failures, which implies "knowing"
+  -- that there parsing failures in the entire document, which implies that pattern matching on
+  -- 'Right' evaluates the entire document.
+  --
+  -- This limits the laziness of the JSON parsing.  For lazier alternatives, see
+  -- 'HaskellWorks.Data.Json.PartialValue.jsonPartialJsonValueAt' or 'HaskellWorks.Data.Json.LightJson.lightJsonAt'.
   jsonValueAt :: a -> Either DecodeError JsonValue
 
 instance JsonValueAt JsonIndex where
@@ -30,7 +53,7 @@
     JsonIndexString  s  -> case ABC.parse parseJsonString s of
       ABC.Fail    {}  -> Left (DecodeError ("Invalid string: '" ++ show (BS.take 20 s) ++ "...'"))
       ABC.Partial _   -> Left (DecodeError "Unexpected end of string")
-      ABC.Done    _ r -> Right (JsonString r)
+      ABC.Done    _ r -> Right (JsonString (T.pack r)) -- TODO optimise
     JsonIndexNumber  s  -> case ABC.parse ABC.rational s of
       ABC.Fail    {}    -> Left (DecodeError ("Invalid number: '" ++ show (BS.take 20 s) ++ "...'"))
       ABC.Partial f     -> case f " " of
@@ -38,11 +61,12 @@
         ABC.Partial _   -> Left (DecodeError "Unexpected end of number")
         ABC.Done    _ r -> Right (JsonNumber r)
       ABC.Done    _ r   -> Right (JsonNumber r)
-    JsonIndexObject  fs -> JsonObject <$> mapM (\f -> (,) <$> parseString (fst f) <*> jsonValueAt (snd f)) fs
+    JsonIndexObject  fs -> JsonObject <$> mapM (\f -> (,) <$> parseText (fst f) <*> jsonValueAt (snd f)) fs
     JsonIndexArray   es -> JsonArray <$> mapM jsonValueAt es
     JsonIndexBool    v  -> Right (JsonBool v)
     JsonIndexNull       -> Right JsonNull
-    where parseString bs = case ABC.parse parseJsonString bs of
+    where parseText bs = T.pack <$> parseString bs -- TODO optimise
+          parseString bs = case ABC.parse parseJsonString bs of
             ABC.Fail    {}  -> Left (DecodeError ("Invalid field: '" ++ show (BS.take 20 bs) ++ "...'"))
             ABC.Partial _   -> Left (DecodeError "Unexpected end of field")
             ABC.Done    _ s -> Right s
diff --git a/test/HaskellWorks/Data/Json/Backend/Simple/CursorSpec.hs b/test/HaskellWorks/Data/Json/Backend/Simple/CursorSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Backend/Simple/CursorSpec.hs
+++ /dev/null
@@ -1,85 +0,0 @@
-{-# LANGUAGE ExplicitForAll            #-}
-{-# LANGUAGE FlexibleContexts          #-}
-{-# LANGUAGE FlexibleInstances         #-}
-{-# LANGUAGE InstanceSigs              #-}
-{-# LANGUAGE MultiParamTypeClasses     #-}
-{-# LANGUAGE NoMonomorphismRestriction #-}
-{-# LANGUAGE OverloadedStrings         #-}
-{-# LANGUAGE ScopedTypeVariables       #-}
-
-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-
-module HaskellWorks.Data.Json.Backend.Simple.CursorSpec
-  ( spec
-  ) where
-
-import Control.Monad
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString                              as BS
-import qualified HaskellWorks.Data.Json.Backend.Simple.Cursor as Z
-import qualified HaskellWorks.Data.Json.Backend.Simple.Fast   as FAST
-import qualified HaskellWorks.Data.Json.Backend.Simple.Value  as V
-import qualified HaskellWorks.Data.TreeCursor                 as TC
-
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: redundant bracket"          :: String) #-}
-
-fc = TC.firstChild
-ns = TC.nextSibling
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Backend.Simple.CursorSpec" $ do
-  describe "Json cursor" $ do
-    describe "For sample Json" $ do
-      let k = FAST.makeCursor ("[[11],[22]]" :: BS.ByteString)
-      -- [  [  1  1 ]  ,  [  2  2 ]  ]
-      -- (( ((      )) )( ((      )) ))
-      it "can navigate" $ requireTest $ do
-        (Z.cursorRank <$>  Just                            k) === Just 1
-        (Z.cursorRank <$>  ns                              k) === Nothing
-        (Z.cursorRank <$>  fc                              k) === Just 2
-        (Z.cursorRank <$> (fc >=> ns                     ) k) === Just 8
-        (Z.cursorRank <$> (fc >=> ns >=> fc              ) k) === Just 9
-        (Z.cursorRank <$> (fc >=> ns >=> fc >=> ns       ) k) === Nothing
-        (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc       ) k) === Just 10
-        (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing
-        (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing
-        (Z.cursorRank <$> (fc >=> fc                     ) k) === Just 3
-        (Z.cursorRank <$> (fc >=> fc >=> ns              ) k) === Nothing
-        (Z.cursorRank <$> (fc >=> fc >=> fc              ) k) === Just 4
-        (Z.cursorRank <$> (fc >=> fc >=> fc >=> ns       ) k) === Nothing
-        (Z.cursorRank <$> (fc >=> fc >=> fc >=> fc       ) k) === Nothing
-      it "can snippet pos" $ requireTest $ do
-        (V.snippetPos <$>  Just                            k) === Just (1, 11)
-        (V.snippetPos <$>  ns                              k) === Nothing
-        (V.snippetPos <$>  fc                              k) === Just (2,  5)
-        (V.snippetPos <$> (fc >=> ns                     ) k) === Just (7, 10)
-        (V.snippetPos <$> (fc >=> ns >=> fc              ) k) === Just (7, 10)
-        (V.snippetPos <$> (fc >=> ns >=> fc >=> ns       ) k) === Nothing
-        (V.snippetPos <$> (fc >=> ns >=> fc >=> fc       ) k) === Just (8,  9)
-        (V.snippetPos <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing
-        (V.snippetPos <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing
-        (V.snippetPos <$> (fc >=> fc                     ) k) === Just (2,  5)
-        (V.snippetPos <$> (fc >=> fc >=> ns              ) k) === Nothing
-        (V.snippetPos <$> (fc >=> fc >=> fc              ) k) === Just (3,  4)
-        (V.snippetPos <$> (fc >=> fc >=> fc >=> ns       ) k) === Nothing
-        (V.snippetPos <$> (fc >=> fc >=> fc >=> fc       ) k) === Nothing
-      it "can snippet" $ requireTest $ do
-        (V.snippet <$>  Just                            k) === Just "[[11],[22]]"
-        (V.snippet <$>  ns                              k) === Nothing
-        (V.snippet <$>  fc                              k) === Just "[11]"
-        (V.snippet <$> (fc >=> ns                     ) k) === Just "[22]"
-        (V.snippet <$> (fc >=> ns >=> fc              ) k) === Just "[22]"
-        (V.snippet <$> (fc >=> ns >=> fc >=> ns       ) k) === Nothing
-        (V.snippet <$> (fc >=> ns >=> fc >=> fc       ) k) === Just "22"
-        (V.snippet <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing
-        (V.snippet <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing
-        (V.snippet <$> (fc >=> fc                     ) k) === Just "[11]"
-        (V.snippet <$> (fc >=> fc >=> ns              ) k) === Nothing
-        (V.snippet <$> (fc >=> fc >=> fc              ) k) === Just "11"
-        (V.snippet <$> (fc >=> fc >=> fc >=> ns       ) k) === Nothing
-        (V.snippet <$> (fc >=> fc >=> fc >=> fc       ) k) === Nothing
diff --git a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/Cursor/BalancedParensSpec.hs b/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/Cursor/BalancedParensSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/Cursor/BalancedParensSpec.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-{-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-
-module HaskellWorks.Data.Json.Backend.Standard.Succinct.Cursor.BalancedParensSpec
-  ( spec
-  ) where
-
-import Data.Word
-import HaskellWorks.Data.Bits.BitShow
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString                                   as BS
-import qualified Data.Vector.Storable                              as DVS
-import qualified HaskellWorks.Data.Json.Backend.Standard.SemiIndex as SI
-
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-
-balancedParensOf2 :: BS.ByteString -> DVS.Vector Word64
-balancedParensOf2 bs = let SI.SemiIndex _ bp = SI.buildSemiIndex bs in bp
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Succinct.Cursor.InterestBitsSpec" $ do
-  it "Evaluating interest bits 2" $ requireTest $ do
-    bitShow (balancedParensOf2 ""           ) === ""
-    bitShow (balancedParensOf2 "  \n \r \t ") === ""
-    bitShow (balancedParensOf2 "1234 "      ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "1.1 "       ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "-1.1e-1 "   ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "false "     ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "true "      ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "\"hello\" " ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "\"\\\"\" "  ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "{ "         ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "} "         ) === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "[ "         ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 "] "         ) === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 ": "         ) === ""
-    bitShow (balancedParensOf2 ", "         ) === ""
-    bitShow (balancedParensOf2 "{{}}"       ) === "11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (balancedParensOf2 " { { } } "  ) === "11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
diff --git a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/Cursor/InterestBitsSpec.hs b/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/Cursor/InterestBitsSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/Cursor/InterestBitsSpec.hs
+++ /dev/null
@@ -1,67 +0,0 @@
-{-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-
-module HaskellWorks.Data.Json.Backend.Standard.Succinct.Cursor.InterestBitsSpec(spec) where
-
-import Data.String
-import Data.Word
-import HaskellWorks.Data.Bits.BitShow
-import HaskellWorks.Data.Bits.BitShown
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString                                                   as BS
-import qualified Data.Vector.Storable                                              as DVS
-import qualified HaskellWorks.Data.Json.Backend.Standard.SemiIndex                 as SI
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson      as J
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.ToInterestBits64 as J
-
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-
-interestBitsOf :: BS.ByteString -> DVS.Vector Word64
-interestBitsOf bs = J.toInterestBits64 (J.toBlankedJsonTyped bs)
-
-interestBitsOf2 :: BS.ByteString -> DVS.Vector Word64
-interestBitsOf2 bs = let SI.SemiIndex ib _ = SI.buildSemiIndex bs in ib
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Succinct.Cursor.InterestBitsSpec" $ do
-  it "Evaluating interest bits" $ requireTest $ do
-    BitShown (interestBitsOf ""           ) === fromString ""
-    BitShown (interestBitsOf "  \n \r \t ") === fromString "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "1234 "      ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "1.1 "       ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "-1.1e-2 "   ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "false "     ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "true "      ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "\"hello\" " ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "\"\\\"\" "  ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "{ "         ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "} "         ) === fromString "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "[ "         ) === fromString "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "] "         ) === fromString "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf ": "         ) === fromString "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf ", "         ) === fromString "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf "{{}}"       ) === fromString "11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    BitShown (interestBitsOf " { { } } "  ) === fromString "01010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-  it "Evaluating interest bits 2" $ requireTest $ do
-    bitShow (interestBitsOf2 ""           ) === ""
-    bitShow (interestBitsOf2 "  \n \r \t ") === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "1234 "      ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "1.1 "       ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "-1.1 "      ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "-1.1e-2 "   ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "false "     ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "true "      ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "\"hello\" " ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "\"\\\"\" "  ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "{ "         ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "} "         ) === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "[ "         ) === "10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "] "         ) === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 ": "         ) === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 ", "         ) === "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 "{{}}"       ) === "11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
-    bitShow (interestBitsOf2 " { { } } "  ) === "01010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000"
diff --git a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/CursorSpec.hs b/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/CursorSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/CursorSpec.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-{-# LANGUAGE ExplicitForAll            #-}
-{-# LANGUAGE FlexibleContexts          #-}
-{-# LANGUAGE FlexibleInstances         #-}
-{-# LANGUAGE InstanceSigs              #-}
-{-# LANGUAGE MultiParamTypeClasses     #-}
-{-# LANGUAGE NoMonomorphismRestriction #-}
-{-# LANGUAGE OverloadedStrings         #-}
-{-# LANGUAGE ScopedTypeVariables       #-}
-
-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Succinct.CursorSpec(spec) where
-
-import Data.Word
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Backend.Standard.Succinct.GenCursorTest
-import HaskellWorks.Data.RankSelect.Poppy512
-import Test.Hspec
-
-import qualified Data.ByteString                              as BS
-import qualified Data.Vector.Storable                         as DVS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Fast as FAST
-import qualified HaskellWorks.Data.Json.Backend.Standard.Slow as SLOW
-
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: redundant bracket"          :: String) #-}
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Succinct.CursorSpec" $ do
-  genTest "DVS.Vector Word64" (SLOW.makeCursor :: String -> JsonCursor BS.ByteString (DVS.Vector Word64) (SimpleBalancedParens (DVS.Vector Word64)))
-  genTest "Poppy512"          (FAST.makeCursor :: String -> JsonCursor BS.ByteString Poppy512 (SimpleBalancedParens (DVS.Vector Word64)))
diff --git a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/GenCursorTest.hs b/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/GenCursorTest.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Backend/Standard/Succinct/GenCursorTest.hs
+++ /dev/null
@@ -1,103 +0,0 @@
-{-# LANGUAGE ExplicitForAll            #-}
-{-# LANGUAGE FlexibleContexts          #-}
-{-# LANGUAGE FlexibleInstances         #-}
-{-# LANGUAGE InstanceSigs              #-}
-{-# LANGUAGE MultiParamTypeClasses     #-}
-{-# LANGUAGE NoMonomorphismRestriction #-}
-{-# LANGUAGE OverloadedStrings         #-}
-{-# LANGUAGE ScopedTypeVariables       #-}
-
-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-
-module HaskellWorks.Data.Json.Backend.Standard.Succinct.GenCursorTest(genTest) where
-
-import Control.Monad
-import HaskellWorks.Data.BalancedParens.BalancedParens
-import HaskellWorks.Data.Bits.BitWise
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Cursor.Token
-import HaskellWorks.Data.Json.Internal.Index
-import HaskellWorks.Data.Json.Internal.Token
-import HaskellWorks.Data.RankSelect.Base.Rank0
-import HaskellWorks.Data.RankSelect.Base.Rank1
-import HaskellWorks.Data.RankSelect.Base.Select1
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString              as BS
-import qualified HaskellWorks.Data.TreeCursor as TC
-
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: redundant bracket"          :: String) #-}
-
-fc = TC.firstChild
-ns = TC.nextSibling
-pn = TC.parent
-ss = TC.subtreeSize
-
-genTest :: forall t u.
-  ( Eq                t
-  , Show              t
-  , Select1           t
-  , Eq                u
-  , Show              u
-  , Rank0             u
-  , Rank1             u
-  , BalancedParens    u
-  , TestBit           u)
-  => String -> (String -> JsonCursor BS.ByteString t u) -> SpecWith ()
-genTest t mkCursor = do
-  describe ("Json cursor of type " ++ t) $ do
-    describe "For empty json array" $ do
-      let cursor = mkCursor "[null]"
-      it "can navigate down and forwards" $ requireTest $ do
-        jsonIndexAt cursor === Right (JsonIndexArray [JsonIndexNull])
-    describe "For sample Json" $ do
-      let cursor = mkCursor "\
-            \{ \
-            \    \"widget\": { \
-            \        \"debug\": \"on\", \
-            \        \"window\": { \
-            \            \"name\": \"main_window\", \
-            \            \"dimensions\": [500, 600.01e-02, true, false, null] \
-            \        } \
-            \    } \
-            \}"
-      it "can navigate up" $ requireTest $ do
-        (                                                                      pn) cursor === Nothing
-        (fc                                                                >=> pn) cursor ===                                    Just cursor
-        (fc >=> ns                                                         >=> pn) cursor ===                                    Just cursor
-        (fc >=> ns >=> fc                                                  >=> pn) cursor === (fc >=> ns                            ) cursor
-        (fc >=> ns >=> fc >=> ns                                           >=> pn) cursor === (fc >=> ns                            ) cursor
-        (fc >=> ns >=> fc >=> ns >=> ns                                    >=> pn) cursor === (fc >=> ns                            ) cursor
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns                             >=> pn) cursor === (fc >=> ns                            ) cursor
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                      >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns               >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns        >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
-      it "can get subtree size" $ requireTest $ do
-        (                                                                      ss) cursor === Just 16
-        (fc                                                                >=> ss) cursor === Just 1
-        (fc >=> ns                                                         >=> ss) cursor === Just 14
-        (fc >=> ns >=> fc                                                  >=> ss) cursor === Just 1
-        (fc >=> ns >=> fc >=> ns                                           >=> ss) cursor === Just 1
-        (fc >=> ns >=> fc >=> ns >=> ns                                    >=> ss) cursor === Just 1
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns                             >=> ss) cursor === Just 10
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                      >=> ss) cursor === Just 1
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns               >=> ss) cursor === Just 1
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns        >=> ss) cursor === Just 1
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ss) cursor === Just 6
-      it "can get token at cursor" $ requireTest $ do
-        (jsonTokenAt                                                                      ) cursor === Just (JsonTokenBraceL                 )
-        (fc                                                                >=> jsonTokenAt) cursor === Just (JsonTokenString   "widget"      )
-        (fc >=> ns                                                         >=> jsonTokenAt) cursor === Just (JsonTokenBraceL                 )
-        (fc >=> ns >=> fc                                                  >=> jsonTokenAt) cursor === Just (JsonTokenString   "debug"       )
-        (fc >=> ns >=> fc >=> ns                                           >=> jsonTokenAt) cursor === Just (JsonTokenString   "on"          )
-        (fc >=> ns >=> fc >=> ns >=> ns                                    >=> jsonTokenAt) cursor === Just (JsonTokenString   "window"      )
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns                             >=> jsonTokenAt) cursor === Just (JsonTokenBraceL                 )
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                      >=> jsonTokenAt) cursor === Just (JsonTokenString   "name"        )
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns               >=> jsonTokenAt) cursor === Just (JsonTokenString   "main_window" )
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns        >=> jsonTokenAt) cursor === Just (JsonTokenString   "dimensions"  )
-        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> jsonTokenAt) cursor === Just (JsonTokenBracketL               )
diff --git a/test/HaskellWorks/Data/Json/CorpusSpec.hs b/test/HaskellWorks/Data/Json/CorpusSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/CorpusSpec.hs
+++ /dev/null
@@ -1,57 +0,0 @@
-{-# LANGUAGE BangPatterns              #-}
-{-# LANGUAGE ExplicitForAll            #-}
-{-# LANGUAGE FlexibleContexts          #-}
-{-# LANGUAGE FlexibleInstances         #-}
-{-# LANGUAGE InstanceSigs              #-}
-{-# LANGUAGE MultiParamTypeClasses     #-}
-{-# LANGUAGE NoMonomorphismRestriction #-}
-{-# LANGUAGE OverloadedStrings         #-}
-{-# LANGUAGE ScopedTypeVariables       #-}
-
-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-
-module HaskellWorks.Data.Json.CorpusSpec(spec) where
-
-import Control.Monad.IO.Class
-import HaskellWorks.Data.BalancedParens.Simple
-import HaskellWorks.Data.Bits.FromBitTextByteString
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString                              as BS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Slow as SLOW
-
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: redundant bracket"          :: String) #-}
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Corpus" $ do
-  it "Corpus 5000B loads properly" $ requireTest $ do
-    inJsonBS                    <- liftIO $ BS.readFile "corpus/5000B.json"
-    inInterestBitsBS            <- liftIO $ BS.readFile "corpus/5000B.json.ib.idx"
-    inInterestBalancedParensBS  <- liftIO $ BS.readFile "corpus/5000B.json.bp.idx"
-    let inInterestBits            = fromBitTextByteString inInterestBitsBS
-    let inInterestBalancedParens  = fromBitTextByteString inInterestBalancedParensBS
-    let !cursor = SLOW.makeCursor inJsonBS
-    let text                    = cursorText      cursor
-    let ib                      = interests       cursor
-    let SimpleBalancedParens bp = balancedParens  cursor
-    text === inJsonBS
-    ib === inInterestBits
-    bp === inInterestBalancedParens
-  it "issue-0001 loads properly" $ requireTest $ do
-    inJsonBS                    <- liftIO $ BS.readFile "corpus/issue-0001.json"
-    inInterestBitsBS            <- liftIO $ BS.readFile "corpus/issue-0001.json.ib.idx"
-    inInterestBalancedParensBS  <- liftIO $ BS.readFile "corpus/issue-0001.json.bp.idx"
-    let inInterestBits            = fromBitTextByteString inInterestBitsBS
-    let inInterestBalancedParens  = fromBitTextByteString inInterestBalancedParensBS
-    let !cursor = SLOW.makeCursor inJsonBS
-    let text                    = cursorText      cursor
-    let ib                      = interests       cursor
-    let SimpleBalancedParens bp = balancedParens  cursor
-    text === inJsonBS
-    ib === inInterestBits
-    bp === inInterestBalancedParens
diff --git a/test/HaskellWorks/Data/Json/Internal/BlankSpec.hs b/test/HaskellWorks/Data/Json/Internal/BlankSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Internal/BlankSpec.hs
+++ /dev/null
@@ -1,51 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module HaskellWorks.Data.Json.Internal.BlankSpec (spec) where
-
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Blank
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString as BS
-
-{-# ANN module ("HLint: ignore Redundant do" :: String) #-}
-
-whenBlankedJsonShouldBe :: BS.ByteString -> BS.ByteString -> Spec
-whenBlankedJsonShouldBe original expected = do
-  it (show original ++ " when blanked json should be " ++ show expected) $ requireTest $ do
-    BS.concat (blankJson [original]) === expected
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Internal.BlankSpec" $ do
-  describe "Can blank json" $ do
-    "\"\""                                `whenBlankedJsonShouldBe` "()"
-    "\"\\\\\""                            `whenBlankedJsonShouldBe` "(  )"
-    "\"\\\\\\\""                          `whenBlankedJsonShouldBe` "(    "
-    "\" \\\\\\\""                         `whenBlankedJsonShouldBe` "(     "
-    "\" \\n\\\\\""                        `whenBlankedJsonShouldBe` "(     )"
-    ""                                    `whenBlankedJsonShouldBe` ""
-    "\"\""                                `whenBlankedJsonShouldBe` "()"
-    "\" \""                               `whenBlankedJsonShouldBe` "( )"
-    "\" a \""                             `whenBlankedJsonShouldBe` "(   )"
-    " \"a \" x"                           `whenBlankedJsonShouldBe` " (  ) x"
-    " \"\"\"\" "                          `whenBlankedJsonShouldBe` " ()() "
-    " [][] "                              `whenBlankedJsonShouldBe` " [][] "
-    " {}{} "                              `whenBlankedJsonShouldBe` " {}{} "
-    " \"a\"b\"c\"d"                       `whenBlankedJsonShouldBe` " ( )b( )d"
-    ""                                    `whenBlankedJsonShouldBe` ""
-    "1"                                   `whenBlankedJsonShouldBe` "1"
-    "11"                                  `whenBlankedJsonShouldBe` "10"
-    "00"                                  `whenBlankedJsonShouldBe` "10"
-    "00"                                  `whenBlankedJsonShouldBe` "10"
-    "-0.12e+34"                           `whenBlankedJsonShouldBe` "100000000"
-    "10.12E-34 "                          `whenBlankedJsonShouldBe` "100000000 "
-    "10.12E-34 12"                        `whenBlankedJsonShouldBe` "100000000 10"
-    " 10.12E-34 -1"                       `whenBlankedJsonShouldBe` " 100000000 10"
-    ""                                    `whenBlankedJsonShouldBe` ""
-    "a"                                   `whenBlankedJsonShouldBe` "a"
-    "z"                                   `whenBlankedJsonShouldBe` "z"
-    " Aaa "                               `whenBlankedJsonShouldBe` " A__ "
-    " Za def "                            `whenBlankedJsonShouldBe` " Z_ d__ "
-    ""                                    `whenBlankedJsonShouldBe` ""
-    " { \"ff\": 1.0, [\"\", true], null}" `whenBlankedJsonShouldBe` " { (  ): 100, [(), t___], n___}"
diff --git a/test/HaskellWorks/Data/Json/LightJsonSpec.hs b/test/HaskellWorks/Data/Json/LightJsonSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/HaskellWorks/Data/Json/LightJsonSpec.hs
@@ -0,0 +1,148 @@
+{-# LANGUAGE FlexibleContexts          #-}
+{-# LANGUAGE FlexibleInstances         #-}
+{-# LANGUAGE MultiParamTypeClasses     #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE OverloadedStrings         #-}
+{-# LANGUAGE ScopedTypeVariables       #-}
+{-# LANGUAGE TupleSections             #-}
+
+module HaskellWorks.Data.Json.LightJsonSpec (spec) where
+
+import Control.Monad
+import Data.Text
+import HaskellWorks.Data.BalancedParens.BalancedParens
+import HaskellWorks.Data.Bits.BitWise
+import HaskellWorks.Data.Json.DecodeError
+import HaskellWorks.Data.Json.LightJson
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Json.Value
+import HaskellWorks.Data.RankSelect.Base.Rank0
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import HaskellWorks.Hspec.Hedgehog
+import Hedgehog
+import Test.Hspec
+
+import qualified Data.Aeson.Parser.Internal                   as AP
+import qualified Data.Attoparsec.ByteString                   as PBS
+import qualified Data.ByteString                              as BS
+import qualified Data.Scientific                              as S
+import qualified Data.Text                                    as T
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast  as FAST
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Slow  as SLOW
+import qualified HaskellWorks.Data.TreeCursor                 as TC
+
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant bracket"  -}
+{- HLINT ignore "Redundant do"       -}
+
+fc :: TC.TreeCursor k => k -> Maybe k
+fc = TC.firstChild
+
+ns :: TC.TreeCursor k => k -> Maybe k
+ns = TC.nextSibling
+
+spec :: Spec
+spec = describe "HaskellWorks.Data.Json.LightJsonSpec" $ do
+  genSpec "DVS.Vector Word64" SLOW.fromString
+  genSpec "CsPoppy"           FAST.fromString
+
+jsonValueVia  :: forall t u.
+  ( BalancedParens u
+  , Rank0 u
+  , Rank1 u
+  , Select1 t
+  , TestBit u)
+  => Maybe (GenericCursor BS.ByteString t u)
+  -> Either DecodeError JsonValue
+jsonValueVia mk = case mk of
+  Just k  -> case lightJsonAt k of
+    LightJsonString t  -> Right (JsonString t)
+    LightJsonNumber bs -> case PBS.parseOnly AP.scientific bs of
+      Right s  -> Right (JsonNumber (S.toRealFloat s))
+      Left msg -> Left (DecodeError msg)
+    LightJsonObject ps -> fmap JsonObject (traverse fields ps)
+    LightJsonArray cs  -> fmap JsonArray (traverse elements cs)
+    LightJsonBool v    -> Right (JsonBool v)
+    LightJsonNull      -> Right JsonNull
+    LightJsonError msg -> Left (DecodeError (T.unpack msg))
+  Nothing -> Left (DecodeError "No such element")
+  where fields :: (Text, GenericCursor BS.ByteString t u) -> Either DecodeError (Text, JsonValue)
+        fields (f, c) = (f,) <$> jsonValueVia (Just c)
+        elements :: GenericCursor BS.ByteString t u -> Either DecodeError JsonValue
+        elements c = jsonValueVia (Just c)
+
+genSpec :: forall t u.
+  ( Select1           t
+  , Rank0             u
+  , Rank1             u
+  , BalancedParens    u
+  , TestBit           u)
+  => String -> (String -> GenericCursor BS.ByteString t u) -> SpecWith ()
+genSpec t makeCursor = do
+  describe ("Json cursor of type " ++ t) $ do
+    let forJson s f = describe ("of value " ++ Prelude.show s) (f (makeCursor s))
+    forJson "{}" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonObject [])
+    forJson " {}" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonObject [])
+    forJson "1234" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonNumber 1234)
+    forJson "\"Hello\"" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonString "Hello")
+    forJson "[]" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonArray [])
+    forJson "true" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonBool True)
+    forJson "false" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonBool False)
+    forJson "null" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right JsonNull
+    forJson "[null]" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonArray [JsonNull])
+      it "should have correct value"      $ requireTest $ jsonValueVia (fc   cursor) === Right  JsonNull
+    forJson "\"codepoint\\u2019s\"" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonString "codepoint’s")
+    forJson "[null, {\"field\": 1}]" $ \cursor -> do
+      it "cursor can navigate to second child of array" $ requireTest $ do
+        jsonValueVia ((fc >=> ns)   cursor) === Right (                     JsonObject [("field", JsonNumber 1)] )
+        jsonValueVia (Just          cursor) === Right (JsonArray [JsonNull, JsonObject [("field", JsonNumber 1)]])
+    describe "For empty json array" $ do
+      let cursor = makeCursor "[]"
+      it "can navigate down and forwards" $ requireTest $ do
+        jsonValueVia (Just cursor) === Right (JsonArray [])
+    describe "For empty json array" $ do
+      let cursor = makeCursor "[null]"
+      it "can navigate down and forwards" $ requireTest $ do
+        jsonValueVia (Just cursor) === Right (JsonArray [JsonNull])
+    describe "For sample Json" $ do
+      let cursor = makeCursor "{ \
+                    \    \"widget\": { \
+                    \        \"debug\": \"on\", \
+                    \        \"window\": { \
+                    \            \"name\": \"main_window\", \
+                    \            \"dimensions\": [500, 600.01e-02, true, false, null] \
+                    \        } \
+                    \    } \
+                    \}" :: GenericCursor BS.ByteString t u
+      it "can navigate down and forwards" $ requireTest $ do
+        let array   = JsonArray [JsonNumber 500, JsonNumber 600.01e-02, JsonBool True, JsonBool False, JsonNull] :: JsonValue
+        let object1 = JsonObject ([("name", JsonString "main_window"), ("dimensions", array)]) :: JsonValue
+        let object2 = JsonObject ([("debug", JsonString "on"), ("window", object1)]) :: JsonValue
+        let object3 = JsonObject ([("widget", object2)]) :: JsonValue
+        jsonValueVia (Just                                                                                                   cursor) === Right object3
+        jsonValueVia ((fc                                                                                                  ) cursor) === Right (JsonString "widget"      )
+        jsonValueVia ((fc >=> ns                                                                                           ) cursor) === Right (object2                  )
+        jsonValueVia ((fc >=> ns >=> fc                                                                                    ) cursor) === Right (JsonString "debug"       )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns                                                                             ) cursor) === Right (JsonString "on"          )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns                                                                      ) cursor) === Right (JsonString "window"      )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns                                                               ) cursor) === Right (object1                  )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                                                        ) cursor) === Right (JsonString "name"        )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns                                                 ) cursor) === Right (JsonString "main_window" )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns                                          ) cursor) === Right (JsonString "dimensions"  )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns                                   ) cursor) === Right (array                    )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                            ) cursor) === Right (JsonNumber 500           )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns                     ) cursor) === Right (JsonNumber 600.01e-02    )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns              ) cursor) === Right (JsonBool True            )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns       ) cursor) === Right (JsonBool False           )
+        jsonValueVia ((fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ns) cursor) === Right JsonNull
diff --git a/test/HaskellWorks/Data/Json/Simple/CursorSpec.hs b/test/HaskellWorks/Data/Json/Simple/CursorSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/HaskellWorks/Data/Json/Simple/CursorSpec.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE FlexibleContexts          #-}
+{-# LANGUAGE FlexibleInstances         #-}
+{-# LANGUAGE MultiParamTypeClasses     #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE OverloadedStrings         #-}
+{-# LANGUAGE ScopedTypeVariables       #-}
+
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+
+module HaskellWorks.Data.Json.Simple.CursorSpec
+  ( spec
+  ) where
+
+import Control.Monad
+import HaskellWorks.Data.Json.LightJson
+import HaskellWorks.Hspec.Hedgehog
+import Hedgehog
+import Test.Hspec
+
+import qualified HaskellWorks.Data.Json.Simple.Cursor      as Z
+import qualified HaskellWorks.Data.Json.Simple.Cursor.Fast as FAST
+import qualified HaskellWorks.Data.Json.Simple.Value       as V
+import qualified HaskellWorks.Data.TreeCursor              as TC
+
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant bracket"  -}
+{- HLINT ignore "Redundant do"       -}
+
+fc = TC.firstChild
+ns = TC.nextSibling
+
+spec :: Spec
+spec = describe "HaskellWorks.Data.Json.Backend.Simple.CursorSpec" $ do
+  describe "Json cursor" $ do
+    describe "For sample Json" $ do
+      let k = FAST.fromByteString "[[11],[22]]"
+      -- [  [  1  1 ]  ,  [  2  2 ]  ]
+      -- (( ((      )) )( ((      )) ))
+      it "can navigate" $ requireTest $ do
+        (Z.cursorRank <$>  Just                            k) === Just 1
+        (Z.cursorRank <$>  ns                              k) === Nothing
+        (Z.cursorRank <$>  fc                              k) === Just 2
+        (Z.cursorRank <$> (fc >=> ns                     ) k) === Just 8
+        (Z.cursorRank <$> (fc >=> ns >=> fc              ) k) === Just 9
+        (Z.cursorRank <$> (fc >=> ns >=> fc >=> ns       ) k) === Nothing
+        (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc       ) k) === Just 10
+        (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing
+        (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing
+        (Z.cursorRank <$> (fc >=> fc                     ) k) === Just 3
+        (Z.cursorRank <$> (fc >=> fc >=> ns              ) k) === Nothing
+        (Z.cursorRank <$> (fc >=> fc >=> fc              ) k) === Just 4
+        (Z.cursorRank <$> (fc >=> fc >=> fc >=> ns       ) k) === Nothing
+        (Z.cursorRank <$> (fc >=> fc >=> fc >=> fc       ) k) === Nothing
+      it "can snippet pos" $ requireTest $ do
+        (V.snippetPos <$>  Just                            k) === Just (1, 11)
+        (V.snippetPos <$>  ns                              k) === Nothing
+        (V.snippetPos <$>  fc                              k) === Just (2,  5)
+        (V.snippetPos <$> (fc >=> ns                     ) k) === Just (7, 10)
+        (V.snippetPos <$> (fc >=> ns >=> fc              ) k) === Just (7, 10)
+        (V.snippetPos <$> (fc >=> ns >=> fc >=> ns       ) k) === Nothing
+        (V.snippetPos <$> (fc >=> ns >=> fc >=> fc       ) k) === Just (8,  9)
+        (V.snippetPos <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing
+        (V.snippetPos <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing
+        (V.snippetPos <$> (fc >=> fc                     ) k) === Just (2,  5)
+        (V.snippetPos <$> (fc >=> fc >=> ns              ) k) === Nothing
+        (V.snippetPos <$> (fc >=> fc >=> fc              ) k) === Just (3,  4)
+        (V.snippetPos <$> (fc >=> fc >=> fc >=> ns       ) k) === Nothing
+        (V.snippetPos <$> (fc >=> fc >=> fc >=> fc       ) k) === Nothing
+      it "can snippet" $ requireTest $ do
+        (V.snippet <$>  Just                            k) === Just "[[11],[22]]"
+        (V.snippet <$>  ns                              k) === Nothing
+        (V.snippet <$>  fc                              k) === Just "[11]"
+        (V.snippet <$> (fc >=> ns                     ) k) === Just "[22]"
+        (V.snippet <$> (fc >=> ns >=> fc              ) k) === Just "[22]"
+        (V.snippet <$> (fc >=> ns >=> fc >=> ns       ) k) === Nothing
+        (V.snippet <$> (fc >=> ns >=> fc >=> fc       ) k) === Just "22"
+        (V.snippet <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing
+        (V.snippet <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing
+        (V.snippet <$> (fc >=> fc                     ) k) === Just "[11]"
+        (V.snippet <$> (fc >=> fc >=> ns              ) k) === Nothing
+        (V.snippet <$> (fc >=> fc >=> fc              ) k) === Just "11"
+        (V.snippet <$> (fc >=> fc >=> fc >=> ns       ) k) === Nothing
+        (V.snippet <$> (fc >=> fc >=> fc >=> fc       ) k) === Nothing
+      it "can lightJsonAt" $ requireTest $ do
+        lightJsonAt k === LightJsonArray []
diff --git a/test/HaskellWorks/Data/Json/Standard/CursorSpec.hs b/test/HaskellWorks/Data/Json/Standard/CursorSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/HaskellWorks/Data/Json/Standard/CursorSpec.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE FlexibleContexts          #-}
+{-# LANGUAGE FlexibleInstances         #-}
+{-# LANGUAGE MultiParamTypeClasses     #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE OverloadedStrings         #-}
+{-# LANGUAGE ScopedTypeVariables       #-}
+
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+
+module HaskellWorks.Data.Json.Standard.CursorSpec(spec) where
+
+import HaskellWorks.Data.Json.Standard.GenCursorTest
+import Test.Hspec
+
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as FAST
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Slow as SLOW
+
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant bracket"  -}
+{- HLINT ignore "Redundant do"       -}
+
+spec :: Spec
+spec = describe "HaskellWorks.Data.Json.Succinct.CursorSpec" $ do
+  genTest "DVS.Vector Word64" SLOW.fromString
+  genTest "CsPoppy"           FAST.fromString
diff --git a/test/HaskellWorks/Data/Json/Standard/GenCursorTest.hs b/test/HaskellWorks/Data/Json/Standard/GenCursorTest.hs
new file mode 100644
--- /dev/null
+++ b/test/HaskellWorks/Data/Json/Standard/GenCursorTest.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE FlexibleContexts          #-}
+{-# LANGUAGE FlexibleInstances         #-}
+{-# LANGUAGE MultiParamTypeClasses     #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE OverloadedStrings         #-}
+{-# LANGUAGE ScopedTypeVariables       #-}
+
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+
+module HaskellWorks.Data.Json.Standard.GenCursorTest(genTest) where
+
+import Control.Monad
+import HaskellWorks.Data.BalancedParens.BalancedParens
+import HaskellWorks.Data.Bits.BitWise
+import HaskellWorks.Data.Json.Internal.Index
+import HaskellWorks.Data.Json.Internal.Standard.Cursor.Token
+import HaskellWorks.Data.Json.Internal.Token
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.RankSelect.Base.Rank0
+import HaskellWorks.Data.RankSelect.Base.Rank1
+import HaskellWorks.Data.RankSelect.Base.Select1
+import HaskellWorks.Hspec.Hedgehog
+import Hedgehog
+import Test.Hspec
+
+import qualified Data.ByteString              as BS
+import qualified HaskellWorks.Data.TreeCursor as TC
+
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant bracket"  -}
+{- HLINT ignore "Redundant do"       -}
+
+fc = TC.firstChild
+ns = TC.nextSibling
+pn = TC.parent
+ss = TC.subtreeSize
+
+genTest :: forall t u.
+  ( Eq                t
+  , Show              t
+  , Select1           t
+  , Eq                u
+  , Show              u
+  , Rank0             u
+  , Rank1             u
+  , BalancedParens    u
+  , TestBit           u)
+  => String -> (String -> GenericCursor BS.ByteString t u) -> SpecWith ()
+genTest t mkCursor = do
+  describe ("Json cursor of type " ++ t) $ do
+    describe "For empty json array" $ do
+      let cursor = mkCursor "[null]"
+      it "can navigate down and forwards" $ requireTest $ do
+        jsonIndexAt cursor === Right (JsonIndexArray [JsonIndexNull])
+    describe "For sample Json" $ do
+      let cursor = mkCursor "\
+            \{ \
+            \    \"widget\": { \
+            \        \"debug\": \"on\", \
+            \        \"window\": { \
+            \            \"name\": \"main_window\", \
+            \            \"dimensions\": [500, 600.01e-02, true, false, null] \
+            \        } \
+            \    } \
+            \}"
+      it "can navigate up" $ requireTest $ do
+        (                                                                      pn) cursor === Nothing
+        (fc                                                                >=> pn) cursor ===                                    Just cursor
+        (fc >=> ns                                                         >=> pn) cursor ===                                    Just cursor
+        (fc >=> ns >=> fc                                                  >=> pn) cursor === (fc >=> ns                            ) cursor
+        (fc >=> ns >=> fc >=> ns                                           >=> pn) cursor === (fc >=> ns                            ) cursor
+        (fc >=> ns >=> fc >=> ns >=> ns                                    >=> pn) cursor === (fc >=> ns                            ) cursor
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns                             >=> pn) cursor === (fc >=> ns                            ) cursor
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                      >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns               >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns        >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> pn) cursor === (fc >=> ns >=> fc >=> ns >=> ns >=> ns) cursor
+      it "can get subtree size" $ requireTest $ do
+        (                                                                      ss) cursor === Just 16
+        (fc                                                                >=> ss) cursor === Just 1
+        (fc >=> ns                                                         >=> ss) cursor === Just 14
+        (fc >=> ns >=> fc                                                  >=> ss) cursor === Just 1
+        (fc >=> ns >=> fc >=> ns                                           >=> ss) cursor === Just 1
+        (fc >=> ns >=> fc >=> ns >=> ns                                    >=> ss) cursor === Just 1
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns                             >=> ss) cursor === Just 10
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                      >=> ss) cursor === Just 1
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns               >=> ss) cursor === Just 1
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns        >=> ss) cursor === Just 1
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> ss) cursor === Just 6
+      it "can get token at cursor" $ requireTest $ do
+        (jsonTokenAt                                                                      ) cursor === Just (JsonTokenBraceL                 )
+        (fc                                                                >=> jsonTokenAt) cursor === Just (JsonTokenString   "widget"      )
+        (fc >=> ns                                                         >=> jsonTokenAt) cursor === Just (JsonTokenBraceL                 )
+        (fc >=> ns >=> fc                                                  >=> jsonTokenAt) cursor === Just (JsonTokenString   "debug"       )
+        (fc >=> ns >=> fc >=> ns                                           >=> jsonTokenAt) cursor === Just (JsonTokenString   "on"          )
+        (fc >=> ns >=> fc >=> ns >=> ns                                    >=> jsonTokenAt) cursor === Just (JsonTokenString   "window"      )
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns                             >=> jsonTokenAt) cursor === Just (JsonTokenBraceL                 )
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc                      >=> jsonTokenAt) cursor === Just (JsonTokenString   "name"        )
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns               >=> jsonTokenAt) cursor === Just (JsonTokenString   "main_window" )
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns        >=> jsonTokenAt) cursor === Just (JsonTokenString   "dimensions"  )
+        (fc >=> ns >=> fc >=> ns >=> ns >=> ns >=> fc >=> ns >=> ns >=> ns >=> jsonTokenAt) cursor === Just (JsonTokenBracketL               )
diff --git a/test/HaskellWorks/Data/Json/Succinct/Cursor/BalancedParensSpec.hs b/test/HaskellWorks/Data/Json/Succinct/Cursor/BalancedParensSpec.hs
deleted file mode 100644
--- a/test/HaskellWorks/Data/Json/Succinct/Cursor/BalancedParensSpec.hs
+++ /dev/null
@@ -1,27 +0,0 @@
-{-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module HaskellWorks.Data.Json.Succinct.Cursor.BalancedParensSpec(spec) where
-
-import Data.String
-import HaskellWorks.Data.Bits.BitShown
-import HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex
-import HaskellWorks.Hspec.Hedgehog
-import Hedgehog
-import Test.Hspec
-
-import qualified Data.ByteString                                              as BS
-import qualified HaskellWorks.Data.Json.Internal.Backend.Standard.BlankedJson as J
-
-{-# ANN module ("HLint: Ignore Redundant do"        :: String) #-}
-
-spec :: Spec
-spec = describe "HaskellWorks.Data.Json.Succinct.Cursor.BalancedParensSpec" $ do
-  it "Blanking JSON should not contain strange characters 1" $ requireTest $ do
-    let blankedJson = J.BlankedJson ["[ [],", "[]]"]
-    let bp = BitShown $ BS.concat (blankedJsonToBalancedParens (J.unBlankedJson blankedJson))
-    bp === fromString "11111111 11111111 00000000 11111111 00000000 00000000"
-  it "Blanking JSON should not contain strange characters 2" $ requireTest $ do
-    let blankedJson = J.BlankedJson ["[ [],", "[]]"]
-    let bp = BitShown $ BS.concat ((compressWordAsBit . blankedJsonToBalancedParens) (J.unBlankedJson blankedJson))
-    bp === fromString "11010000"
diff --git a/test/HaskellWorks/Data/Json/Token/TokenizeSpec.hs b/test/HaskellWorks/Data/Json/Token/TokenizeSpec.hs
--- a/test/HaskellWorks/Data/Json/Token/TokenizeSpec.hs
+++ b/test/HaskellWorks/Data/Json/Token/TokenizeSpec.hs
@@ -2,15 +2,15 @@
 
 module HaskellWorks.Data.Json.Token.TokenizeSpec (spec) where
 
-import Data.ByteString                                                 (ByteString)
-import HaskellWorks.Data.Json.Internal.Backend.Standard.Token.Tokenize
+import Data.ByteString                                         (ByteString)
+import HaskellWorks.Data.Json.Internal.Standard.Token.Tokenize
 import HaskellWorks.Hspec.Hedgehog
 import Hedgehog
 import Test.Hspec
 
 import qualified Data.Attoparsec.ByteString.Char8 as BC
 
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
+{- HLINT ignore "Redundant do"       -}
 
 parseJsonToken' :: ByteString -> Either String (JsonToken String Double)
 parseJsonToken' = BC.parseOnly parseJsonToken
diff --git a/test/HaskellWorks/Data/Json/TypeSpec.hs b/test/HaskellWorks/Data/Json/TypeSpec.hs
--- a/test/HaskellWorks/Data/Json/TypeSpec.hs
+++ b/test/HaskellWorks/Data/Json/TypeSpec.hs
@@ -1,7 +1,5 @@
-{-# LANGUAGE ExplicitForAll            #-}
 {-# LANGUAGE FlexibleContexts          #-}
 {-# LANGUAGE FlexibleInstances         #-}
-{-# LANGUAGE InstanceSigs              #-}
 {-# LANGUAGE MultiParamTypeClasses     #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE OverloadedStrings         #-}
@@ -14,8 +12,8 @@
 import Control.Monad
 import HaskellWorks.Data.BalancedParens.BalancedParens
 import HaskellWorks.Data.Bits.BitWise
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
-import HaskellWorks.Data.Json.Type
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
+import HaskellWorks.Data.Json.Standard.Cursor.Type
 import HaskellWorks.Data.RankSelect.Base.Rank0
 import HaskellWorks.Data.RankSelect.Base.Rank1
 import HaskellWorks.Data.RankSelect.Base.Select1
@@ -23,34 +21,30 @@
 import Hedgehog
 import Test.Hspec
 
-import qualified Data.ByteString                              as BS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Fast as FAST
-import qualified HaskellWorks.Data.Json.Backend.Standard.Slow as SLOW
-import qualified HaskellWorks.Data.TreeCursor                 as TC
+import qualified Data.ByteString                             as BS
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as FAST
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Slow as SLOW
+import qualified HaskellWorks.Data.TreeCursor                as TC
 
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: redundant bracket"          :: String) #-}
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant bracket"  -}
+{- HLINT ignore "Redundant do"       -}
 
 fc = TC.firstChild
 ns = TC.nextSibling
 
 spec :: Spec
 spec = describe "HaskellWorks.Data.Json.Succinct.CursorSpec" $ do
-  genSpec "DVS.Vector Word64" SLOW.makeCursor
-  genSpec "Poppy512"          FAST.makeCursor
+  genSpec "DVS.Vector Word64" SLOW.fromString
+  genSpec "CsPoppy"           FAST.fromString
 
 genSpec :: forall t u.
-  ( Eq                t
-  , Show              t
-  , Select1           t
-  , Eq                u
-  , Show              u
+  ( Select1           t
   , Rank0             u
   , Rank1             u
   , BalancedParens    u
   , TestBit           u)
-  => String -> (String -> JsonCursor BS.ByteString t u) -> SpecWith ()
+  => String -> (String -> GenericCursor BS.ByteString t u) -> SpecWith ()
 genSpec t makeCursor = do
   describe ("Json cursor of type " ++ t) $ do
     let forJson s f = describe ("of value " ++ show s) (f (makeCursor s))
@@ -95,7 +89,7 @@
                     \            \"dimensions\": [500, 600.01e-02, true, false, null] \
                     \        } \
                     \    } \
-                    \}" :: JsonCursor BS.ByteString t u
+                    \}" :: GenericCursor BS.ByteString t u
       it "can navigate down and forwards" $ requireTest $ do
         (                                                                      jsonTypeAt) cursor === Just JsonTypeObject
         (fc                                                                >=> jsonTypeAt) cursor === Just JsonTypeString
diff --git a/test/HaskellWorks/Data/Json/ValueSpec.hs b/test/HaskellWorks/Data/Json/ValueSpec.hs
--- a/test/HaskellWorks/Data/Json/ValueSpec.hs
+++ b/test/HaskellWorks/Data/Json/ValueSpec.hs
@@ -1,7 +1,5 @@
-{-# LANGUAGE ExplicitForAll            #-}
 {-# LANGUAGE FlexibleContexts          #-}
 {-# LANGUAGE FlexibleInstances         #-}
-{-# LANGUAGE InstanceSigs              #-}
 {-# LANGUAGE MultiParamTypeClasses     #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE OverloadedStrings         #-}
@@ -14,9 +12,9 @@
 import Control.Monad
 import HaskellWorks.Data.BalancedParens.BalancedParens
 import HaskellWorks.Data.Bits.BitWise
-import HaskellWorks.Data.Json.Backend.Standard.Cursor
 import HaskellWorks.Data.Json.DecodeError
 import HaskellWorks.Data.Json.Internal.Index
+import HaskellWorks.Data.Json.Standard.Cursor.Generic
 import HaskellWorks.Data.Json.Value
 import HaskellWorks.Data.RankSelect.Base.Rank0
 import HaskellWorks.Data.RankSelect.Base.Rank1
@@ -25,22 +23,22 @@
 import Hedgehog
 import Test.Hspec
 
-import qualified Data.ByteString                              as BS
-import qualified HaskellWorks.Data.Json.Backend.Standard.Fast as FAST
-import qualified HaskellWorks.Data.Json.Backend.Standard.Slow as SLOW
-import qualified HaskellWorks.Data.TreeCursor                 as TC
+import qualified Data.ByteString                             as BS
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Fast as FAST
+import qualified HaskellWorks.Data.Json.Standard.Cursor.Slow as SLOW
+import qualified HaskellWorks.Data.TreeCursor                as TC
 
-{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
-{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
-{-# ANN module ("HLint: redundant bracket"          :: String) #-}
+{- HLINT ignore "Reduce duplication" -}
+{- HLINT ignore "Redundant bracket"  -}
+{- HLINT ignore "Redundant do"       -}
 
 fc = TC.firstChild
 ns = TC.nextSibling
 
 spec :: Spec
 spec = describe "HaskellWorks.Data.Json.ValueSpec" $ do
-  genSpec "DVS.Vector Word64" SLOW.makeCursor
-  genSpec "Poppy512"          FAST.makeCursor
+  genSpec "DVS.Vector Word64" SLOW.fromString
+  genSpec "CsPoppy"           FAST.fromString
 
 jsonValueVia  ::
   ( BalancedParens u
@@ -48,22 +46,18 @@
   , Rank1 u
   , Select1 t
   , TestBit u)
-  => Maybe (JsonCursor BS.ByteString t u) -> Either DecodeError JsonValue
+  => Maybe (GenericCursor BS.ByteString t u) -> Either DecodeError JsonValue
 jsonValueVia mk = case mk of
   Just k  -> (jsonIndexAt >=> jsonValueAt) k
   Nothing -> Left (DecodeError "No such element")
 
 genSpec :: forall t u.
-  ( Eq                t
-  , Show              t
-  , Select1           t
-  , Eq                u
-  , Show              u
+  ( Select1           t
   , Rank0             u
   , Rank1             u
   , BalancedParens    u
   , TestBit           u)
-  => String -> (String -> JsonCursor BS.ByteString t u) -> SpecWith ()
+  => String -> (String -> GenericCursor BS.ByteString t u) -> SpecWith ()
 genSpec t makeCursor = do
   describe ("Json cursor of type " ++ t) $ do
     let forJson s f = describe ("of value " ++ show s) (f (makeCursor s))
@@ -86,6 +80,9 @@
     forJson "[null]" $ \cursor -> do
       it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonArray [JsonNull])
       it "should have correct value"      $ requireTest $ jsonValueVia (fc   cursor) === Right  JsonNull
+      it "should have correct value"      $ requireTest $ jsonValueVia (fc   cursor) === Right  JsonNull
+    forJson "\"codepoint\\u2019s\"" $ \cursor -> do
+      it "should have correct value"      $ requireTest $ jsonValueVia (Just cursor) === Right (JsonString "codepoint’s")
     forJson "[null, {\"field\": 1}]" $ \cursor -> do
       it "cursor can navigate to second child of array" $ requireTest $ do
         jsonValueVia ((fc >=> ns)   cursor) === Right (                     JsonObject [("field", JsonNumber 1)] )
@@ -107,7 +104,7 @@
                     \            \"dimensions\": [500, 600.01e-02, true, false, null] \
                     \        } \
                     \    } \
-                    \}" :: JsonCursor BS.ByteString t u
+                    \}" :: GenericCursor BS.ByteString t u
       it "can navigate down and forwards" $ requireTest $ do
         let array   = JsonArray [JsonNumber 500, JsonNumber 600.01e-02, JsonBool True, JsonBool False, JsonNull] :: JsonValue
         let object1 = JsonObject ([("name", JsonString "main_window"), ("dimensions", array)]) :: JsonValue
