packages feed

json-query-0.2.0.0: src/Json/Context.hs

{-# language BangPatterns #-}

module Json.Context
  ( Context(..)
    -- * Encoding
  , builderUtf8
    -- * Conversion
  , toPath
  ) where

import Json.Path (Path)
import Data.Text.Short (ShortText)
import Data.Bytes.Builder (Builder)

import qualified Json.Path as Path

-- | A finger into a json value indicating where a parser is
-- currently operating. When a parser focuses on a key-value
-- pair in a map, it adds 'Key' constructor to the context, and
-- when it focuses on an element of an array, it adds an 'Index'
-- constructor. Like all zipper-like data structures, it is, in
-- a sense, reversed, which makes it cheap to construct while
-- parsing.
data Context
  = Top
  | Key !ShortText !Context
  | Index !Int !Context
  deriving (Eq,Show)

-- | Reverse the context, converting it to a 'Path'.
-- For example, toPath performs this conversion:
--
-- > 12.bar.foo.Top ==> foo.bar.12.Nil
toPath :: Context -> Path
toPath = go Path.Nil where
  go !acc Top = acc
  go !acc (Key k xs) = go (Path.Key k acc) xs
  go !acc (Index i xs) = go (Path.Index i acc) xs

-- | Convert 'Context' to textual representation using UTF-8 as the encoding
-- scheme. This reverses the context to present it in the expected order.
builderUtf8 :: Context -> Builder
builderUtf8 ctx0 = Path.builderUtf8 (toPath ctx0)