diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for json-syntax
 
+## 0.2.7.1 -- 2024-01-29
+
+* Update package metadata.
+
 ## 0.2.7.0 -- 2023-10-05
 
 * Add `decodeNewlineDelimited`.
@@ -19,7 +23,7 @@
 * Add `ToValue` instances for `Word`, `Text`, `Value`,
   `Scientific`, list (i.e. `[]`), the unit type (i.e. `()`),
 * Add `text` and `shortText` for value construction.
-  
+
 
 ## 0.2.4.0 -- 2023-06-27
 
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,3 @@
 import Distribution.Simple
+
 main = defaultMain
diff --git a/bench/Main.hs b/bench/Main.hs
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -1,20 +1,19 @@
-{-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
 
-import Gauge.Main (defaultMain,bgroup,bench,whnf)
+import Gauge.Main (bench, bgroup, defaultMain, whnf)
 
 import Metrics1024 (encodedMetrics1024)
-import Twitter100 (encodedTwitter100,byteStringTwitter100)
-import Url100 (encodedUrl100,byteStringUrl100)
+import Twitter100 (byteStringTwitter100, encodedTwitter100)
+import Url100 (byteStringUrl100, encodedUrl100)
 
+import qualified Data.Aeson as Aeson
+import qualified Data.ByteString.Lazy as LBS
 import qualified Data.Bytes as Bytes
 import qualified Data.Bytes.Builder as BLDR
 import qualified Data.Bytes.Chunks as Chunks
-import qualified Data.ByteString.Lazy as LBS
 import qualified Json as J
 import qualified Json.Smile as Smile
-import qualified Data.Aeson as Aeson
 
 main :: IO ()
 main = do
@@ -31,58 +30,80 @@
     Nothing -> fail "aeson failed to decode twitter-100"
     Just (v :: Aeson.Value) -> pure v
   defaultMain
-    [ bgroup "json"
-      [ bgroup "twitter"
-        [ bgroup "100"
-          [ bench "decode" $ whnf
-              (\b -> J.decode (Bytes.fromByteArray b))
-              encodedTwitter100
-          , bench "encode" $ whnf
-              (\v -> Chunks.length (BLDR.run 128 (J.encode v)))
-              valueTwitter100
-          , bench "encode-smile" $ whnf
-              (\v -> Chunks.length (BLDR.run 128 (Smile.encode v)))
-              valueTwitter100
-          ]
-        ]
-      , bgroup "url"
-        [ bgroup "100"
-          [ bench "decode" $ whnf
-              (\b -> J.decode (Bytes.fromByteArray b))
-              encodedUrl100
-          , bench "encode" $ whnf
-              (\v -> Chunks.length (BLDR.run 128 (J.encode v)))
-              valueUrl100
-          , bench "encode-smile" $ whnf
-              (\v -> Chunks.length (BLDR.run 128 (Smile.encode v)))
-              valueUrl100
-          ]
-        ]
-      , bgroup "metrics"
-        [ bgroup "1024"
-          [ bench "encode" $ whnf
-              (\v -> Chunks.length (BLDR.run 128 (J.encode v)))
-              valueMetrics1024
-          , bench "encode-smile" $ whnf
-              (\v -> Chunks.length (BLDR.run 128 (Smile.encode v)))
-              valueMetrics1024
-          ]
-        ]
-      ]
-    , bgroup "aeson"
-      [ bgroup "twitter"
-        [ bgroup "100"
-          [ bench "decode"
-              (whnf (Aeson.decodeStrict' @Aeson.Value) byteStringTwitter100)
-          , bench "encode" $ whnf
-              (\v -> LBS.length (Aeson.encode v))
-              aesonValueTwitter100
-          ]
+    [ bgroup
+        "json"
+        [ bgroup
+            "twitter"
+            [ bgroup
+                "100"
+                [ bench "decode" $
+                    whnf
+                      (\b -> J.decode (Bytes.fromByteArray b))
+                      encodedTwitter100
+                , bench "encode" $
+                    whnf
+                      (\v -> Chunks.length (BLDR.run 128 (J.encode v)))
+                      valueTwitter100
+                , bench "encode-smile" $
+                    whnf
+                      (\v -> Chunks.length (BLDR.run 128 (Smile.encode v)))
+                      valueTwitter100
+                ]
+            ]
+        , bgroup
+            "url"
+            [ bgroup
+                "100"
+                [ bench "decode" $
+                    whnf
+                      (\b -> J.decode (Bytes.fromByteArray b))
+                      encodedUrl100
+                , bench "encode" $
+                    whnf
+                      (\v -> Chunks.length (BLDR.run 128 (J.encode v)))
+                      valueUrl100
+                , bench "encode-smile" $
+                    whnf
+                      (\v -> Chunks.length (BLDR.run 128 (Smile.encode v)))
+                      valueUrl100
+                ]
+            ]
+        , bgroup
+            "metrics"
+            [ bgroup
+                "1024"
+                [ bench "encode" $
+                    whnf
+                      (\v -> Chunks.length (BLDR.run 128 (J.encode v)))
+                      valueMetrics1024
+                , bench "encode-smile" $
+                    whnf
+                      (\v -> Chunks.length (BLDR.run 128 (Smile.encode v)))
+                      valueMetrics1024
+                ]
+            ]
         ]
-      , bgroup "url"
-        [ bgroup "100"
-          [ bench "decode" (whnf (Aeson.decodeStrict' @Aeson.Value) byteStringUrl100)
-          ]
+    , bgroup
+        "aeson"
+        [ bgroup
+            "twitter"
+            [ bgroup
+                "100"
+                [ bench
+                    "decode"
+                    (whnf (Aeson.decodeStrict' @Aeson.Value) byteStringTwitter100)
+                , bench "encode" $
+                    whnf
+                      (\v -> LBS.length (Aeson.encode v))
+                      aesonValueTwitter100
+                ]
+            ]
+        , bgroup
+            "url"
+            [ bgroup
+                "100"
+                [ bench "decode" (whnf (Aeson.decodeStrict' @Aeson.Value) byteStringUrl100)
+                ]
+            ]
         ]
-      ]
     ]
diff --git a/common/Metrics1024.hs b/common/Metrics1024.hs
--- a/common/Metrics1024.hs
+++ b/common/Metrics1024.hs
@@ -1,20 +1,21 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
+
 module Metrics1024
   ( encodedMetrics1024
   , byteStringMetrics1024
   ) where
 
 import Data.ByteString (ByteString)
-import Data.ByteString.Short (ShortByteString,toShort)
+import Data.ByteString.Short (ShortByteString, toShort)
 import Data.Primitive (ByteArray)
 import Data.Text.Encoding (encodeUtf8)
 import NeatInterpolation (text)
 
-import qualified Data.Primitive as PM
 import qualified Data.ByteString.Short.Internal as BSS
+import qualified Data.Primitive as PM
 
-shortByteStringToByteArray :: ShortByteString -> ByteArray 
+shortByteStringToByteArray :: ShortByteString -> ByteArray
 shortByteStringToByteArray (BSS.SBS x) = PM.ByteArray x
 
 encodedMetrics1024 :: ByteArray
@@ -22,8 +23,9 @@
   shortByteStringToByteArray (toShort byteStringMetrics1024)
 
 byteStringMetrics1024 :: ByteString
-byteStringMetrics1024 = encodeUtf8
-  [text|
+byteStringMetrics1024 =
+  encodeUtf8
+    [text|
     [ {"@id":"1E7nJ7Ki1ei1mSOuy","@service":"npm","@historical":false,"@timestamp":"2022-02-01T15:10:00Z","@row":"1","organization.acronym":"nyc","agent.type":"freight","host.address":"192.0.2.43","host.ip":"192.0.2.43","host.model":"unknown","host.model_oid":"1.3.6.1.4.1.14988.1","host.vendor":"mikrotik","component.cpu.utilization":0,"component.name":"","host.hostname":"NYC-S75-APT4215"}
     , {"@id":"1E7nJ7SponsUYpH9l","@service":"npm","@historical":false,"@timestamp":"2022-02-01T15:10:00Z","@row":"2","organization.acronym":"nyc","agent.type":"freight","host.address":"192.0.2.43","host.ip":"192.0.2.43","host.model":"unknown","host.model_oid":"1.3.6.1.4.1.14988.1","host.vendor":"mikrotik","component.cpu.utilization":0,"component.name":"","host.hostname":"NYC-S75-APT4215"}
     , {"@id":"1E7nJ7VyTvxK5KDVi","@service":"npm","@historical":false,"@timestamp":"2022-02-01T15:10:00Z","@row":"3","organization.acronym":"nyc","agent.type":"freight","host.address":"192.0.2.43","host.ip":"192.0.2.43","host.model":"unknown","host.model_oid":"1.3.6.1.4.1.14988.1","host.vendor":"mikrotik","component.cpu.utilization":0,"component.name":"","host.hostname":"NYC-S75-APT4215"}
diff --git a/common/Person.hs b/common/Person.hs
--- a/common/Person.hs
+++ b/common/Person.hs
@@ -1,20 +1,21 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
+
 module Person
   ( encodedPerson
   , encodedFlattenedPerson
   ) where
 
 import Data.ByteString (ByteString)
-import Data.ByteString.Short (ShortByteString,toShort)
+import Data.ByteString.Short (ShortByteString, toShort)
 import Data.Primitive (ByteArray)
 import Data.Text.Encoding (encodeUtf8)
 import NeatInterpolation (text)
 
-import qualified Data.Primitive as PM
 import qualified Data.ByteString.Short.Internal as BSS
+import qualified Data.Primitive as PM
 
-shortByteStringToByteArray :: ShortByteString -> ByteArray 
+shortByteStringToByteArray :: ShortByteString -> ByteArray
 shortByteStringToByteArray (BSS.SBS x) = PM.ByteArray x
 
 encodedPerson :: ByteArray
@@ -26,8 +27,9 @@
   shortByteStringToByteArray (toShort byteStringFlattenedPerson)
 
 byteStringPerson :: ByteString
-byteStringPerson = encodeUtf8
-  [text|
+byteStringPerson =
+  encodeUtf8
+    [text|
     { "name": "bilbo"
     , "occupation":
       { "name": "burglar"
@@ -39,8 +41,9 @@
   |]
 
 byteStringFlattenedPerson :: ByteString
-byteStringFlattenedPerson = encodeUtf8
-  [text|
+byteStringFlattenedPerson =
+  encodeUtf8
+    [text|
     { "name": "bilbo"
     , "occupation.name": "burglar"
     , "occupation.start": "2022-05-30"
@@ -48,4 +51,3 @@
     , "favorites": ["adventures","lunch"]
     }
   |]
-
diff --git a/common/Twitter100.hs b/common/Twitter100.hs
--- a/common/Twitter100.hs
+++ b/common/Twitter100.hs
@@ -1,20 +1,21 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
+
 module Twitter100
   ( encodedTwitter100
   , byteStringTwitter100
   ) where
 
 import Data.ByteString (ByteString)
-import Data.ByteString.Short (ShortByteString,toShort)
+import Data.ByteString.Short (ShortByteString, toShort)
 import Data.Primitive (ByteArray)
 import Data.Text.Encoding (encodeUtf8)
 import NeatInterpolation (text)
 
-import qualified Data.Primitive as PM
 import qualified Data.ByteString.Short.Internal as BSS
+import qualified Data.Primitive as PM
 
-shortByteStringToByteArray :: ShortByteString -> ByteArray 
+shortByteStringToByteArray :: ShortByteString -> ByteArray
 shortByteStringToByteArray (BSS.SBS x) = PM.ByteArray x
 
 encodedTwitter100 :: ByteArray
@@ -22,8 +23,9 @@
   shortByteStringToByteArray (toShort byteStringTwitter100)
 
 byteStringTwitter100 :: ByteString
-byteStringTwitter100 = encodeUtf8
-  [text|
+byteStringTwitter100 =
+  encodeUtf8
+    [text|
     {
         "completed_in": 1.000000,
         "max_id": 30121530767708160,
@@ -1864,4 +1866,3 @@
         "since_id_str": "0"
     }
   |]
-
diff --git a/common/Url100.hs b/common/Url100.hs
--- a/common/Url100.hs
+++ b/common/Url100.hs
@@ -1,20 +1,21 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
+
 module Url100
   ( encodedUrl100
   , byteStringUrl100
   ) where
 
 import Data.ByteString (ByteString)
-import Data.ByteString.Short (ShortByteString,toShort)
+import Data.ByteString.Short (ShortByteString, toShort)
 import Data.Primitive (ByteArray)
 import Data.Text.Encoding (encodeUtf8)
 import NeatInterpolation (text)
 
-import qualified Data.Primitive as PM
 import qualified Data.ByteString.Short.Internal as BSS
+import qualified Data.Primitive as PM
 
-shortByteStringToByteArray :: ShortByteString -> ByteArray 
+shortByteStringToByteArray :: ShortByteString -> ByteArray
 shortByteStringToByteArray (BSS.SBS x) = PM.ByteArray x
 
 encodedUrl100 :: ByteArray
@@ -22,8 +23,9 @@
   shortByteStringToByteArray (toShort byteStringUrl100)
 
 byteStringUrl100 :: ByteString
-byteStringUrl100 = encodeUtf8
-  [text|
+byteStringUrl100 =
+  encodeUtf8
+    [text|
     [ "https://balance.example.com/aunt.htm"
     , "http://anger.example.com/"
     , "https://www.example.edu/basket/branch#boat"
@@ -126,5 +128,3 @@
     , "http://attack.example.org/"
     ]
   |]
-
-
diff --git a/json-syntax.cabal b/json-syntax.cabal
--- a/json-syntax.cabal
+++ b/json-syntax.cabal
@@ -1,7 +1,7 @@
-cabal-version: 2.2
-name: json-syntax
-version: 0.2.7.0
-synopsis: High-performance JSON parser and encoder
+cabal-version:   2.2
+name:            json-syntax
+version:         0.2.7.1
+synopsis:        High-performance JSON parser and encoder
 description:
   This library parses JSON into a @Value@ type that is consistent with the
   ABNF described in [RFC 7159](https://tools.ietf.org/html/rfc7159). The
@@ -14,77 +14,81 @@
   and typeclasses are outside the scope of this library. If anyone writes a
   library that offers users these conveniences open a issue so that the
   @json-syntax@ documentation can point users to it.
-homepage: https://github.com/byteverse/json-syntax
-bug-reports: https://github.com/byteverse/json-syntax/issues
-license: BSD-3-Clause
-license-file: LICENSE
-author: Andrew Martin
-maintainer: andrew.thaddeus@gmail.com
-copyright: 2019 Andrew Martin
-category: Data
-build-type: Simple
-extra-source-files: CHANGELOG.md
 
+homepage:        https://github.com/byteverse/json-syntax
+bug-reports:     https://github.com/byteverse/json-syntax/issues
+license:         BSD-3-Clause
+license-file:    LICENSE
+author:          Andrew Martin
+maintainer:      amartin@layer3com.com
+copyright:       2019 Andrew Martin
+category:        Data
+build-type:      Simple
+extra-doc-files: CHANGELOG.md
+
 library
   exposed-modules:
     Json
     Json.Flatten
     Json.Smile
+
   build-depends:
-    , array-builder >=0.1 && <0.2
-    , array-chunks >=0.1.3 && <0.2
-    , base >=4.15 && <5
-    , bytebuild >=0.3.10 && <0.4
-    , byteslice >=0.2.9 && <0.3
-    , bytesmith >=0.3.8 && <0.4
-    , bytestring >=0.10.8 && <0.12
-    , contiguous >=0.6 && <0.7
-    , natural-arithmetic >=0.1.2 && <0.3
-    , primitive >=0.7 && <0.10
-    , run-st >=0.1.1 && <0.2
-    , scientific-notation >=0.1.6 && <0.2
-    , text >=2.0
-    , text-short >=0.1.3 && <0.2
-    , transformers >=0.5.6.2
-    , word-compat >=0.0.3
-    , zigzag >=0.0.1
-  hs-source-dirs: src
+    , array-builder        >=0.1    && <0.2
+    , array-chunks         >=0.1.3  && <0.2
+    , base                 >=4.15   && <5
+    , bytebuild            >=0.3.10 && <0.4
+    , byteslice            >=0.2.9  && <0.3
+    , bytesmith            >=0.3.8  && <0.4
+    , bytestring           >=0.10.8 && <0.12
+    , contiguous           >=0.6    && <0.7
+    , natural-arithmetic   >=0.1.2  && <0.3
+    , primitive            >=0.7    && <0.10
+    , run-st               >=0.1.1  && <0.2
+    , scientific-notation  >=0.1.6  && <0.2
+    , text                 >=2.0.2  && <2.1
+    , text-short           >=0.1.3  && <0.2
+    , transformers         >=0.5.6  && <0.6
+    , word-compat          >=0.0.6  && <0.1
+    , zigzag               >=0.0.1  && <0.1
+
+  hs-source-dirs:   src
   default-language: Haskell2010
-  ghc-options: -Wall -O2
+  ghc-options:      -Wall -O2
 
 test-suite test
   default-language: Haskell2010
-  type: exitcode-stdio-1.0
-  hs-source-dirs: test, common
-  main-is: Main.hs
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   test common
+  main-is:          Main.hs
   other-modules:
-    Twitter100
     Person
-  ghc-options: -Wall -O2
+    Twitter100
+
+  ghc-options:      -Wall -O2
   build-depends:
-    , QuickCheck >=2.14.2
-    , aeson >=2.0.2
+    , aeson                >=2.0.2
     , array-chunks
-    , base >=4.12.0.0 && <5
+    , base                 >=4.12.0.0 && <5
     , bytebuild
-    , byteslice >=0.1.3
+    , byteslice            >=0.1.3
     , bytestring
     , containers
     , json-syntax
-    , neat-interpolation >=0.3.2
+    , neat-interpolation   >=0.3.2
     , primitive
+    , QuickCheck           >=2.14.2
     , scientific
-    , scientific-notation >=0.1.1
-    , tasty >=1.2.3 && <1.3
-    , tasty-hunit >=0.10.0.2 && <0.11
-    , tasty-golden >=2.0 && <2.4
-    , tasty-quickcheck >=0.10.1.2 && <0.11
-    , text >=1.2
+    , scientific-notation  >=0.1.1
+    , tasty                >=1.2.3    && <1.3
+    , tasty-golden         >=2.0      && <2.4
+    , tasty-hunit          >=0.10.0.2 && <0.11
+    , tasty-quickcheck     >=0.10.1.2 && <0.11
+    , text                 >=2.0.2    && <2.1
     , text-short
     , vector
 
 benchmark bench
-  type: exitcode-stdio-1.0
+  type:             exitcode-stdio-1.0
   build-depends:
     , aeson
     , base
@@ -93,15 +97,20 @@
     , bytestring
     , gauge
     , json-syntax
-    , neat-interpolation >=0.3.2
+    , neat-interpolation   >=0.3.2
     , primitive
-    , text >=1.2
-    , scientific-notation >=0.1.1
-  ghc-options: -Wall -O2
+    , scientific-notation  >=0.1.1
+    , text                 >=2.0.2 && <2.1
+
+  ghc-options:      -Wall -O2
   default-language: Haskell2010
-  hs-source-dirs: bench, common
-  main-is: Main.hs
+  hs-source-dirs:   bench common
+  main-is:          Main.hs
   other-modules:
+    Metrics1024
     Twitter100
     Url100
-    Metrics1024
+
+source-repository head
+  type:     git
+  location: git://github.com/byteverse/json-syntax.git
diff --git a/src/Json.hs b/src/Json.hs
--- a/src/Json.hs
+++ b/src/Json.hs
@@ -1,23 +1,24 @@
-{-# language BangPatterns #-}
-{-# language BinaryLiterals #-}
-{-# language BlockArguments #-}
-{-# language DerivingStrategies #-}
-{-# language DeriveAnyClass #-}
-{-# language LambdaCase #-}
-{-# language MagicHash #-}
-{-# language NamedFieldPuns #-}
-{-# language PatternSynonyms #-}
-{-# language TypeApplications #-}
-{-# language UnboxedSums #-}
-{-# language UnboxedTuples #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE BinaryLiterals #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE UnboxedTuples #-}
 
 module Json
   ( -- * Types
-    Value(..)
-  , Member(..)
-  , SyntaxException(..)
+    Value (..)
+  , Member (..)
+  , SyntaxException (..)
+
     -- * Classes
-  , ToValue(..)
+  , ToValue (..)
+
     -- * Functions
   , decode
   , decodeNewlineDelimited
@@ -27,11 +28,14 @@
   , toText
   , toBytes
   , toByteArray
-    -- * Infix Synonyms 
+
+    -- * Infix Synonyms
   , pattern (:->)
+
     -- * Constants
   , emptyArray
   , emptyObject
+
     -- * Value Construction
   , int
   , int8
@@ -45,8 +49,10 @@
   , bool
   , text
   , shortText
+
     -- * Array Construction
   , arrayFromList
+
     -- * Object Construction
   , objectFromList
   , object1
@@ -67,62 +73,63 @@
   , object16
   ) where
 
-import Prelude hiding (Bool(True,False))
+import Prelude hiding (Bool (False, True))
 
 import Control.Exception (Exception)
-import Control.Monad.ST (ST,runST)
+import Control.Monad.ST (ST, runST)
 import Control.Monad.ST.Run (runSmallArrayST)
-import Data.Bits ((.&.),(.|.),unsafeShiftR)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.Except (except, runExceptT)
+import Data.Bits (unsafeShiftR, (.&.), (.|.))
 import Data.Builder.ST (Builder)
+import Data.Bytes.Chunks (Chunks)
 import Data.Bytes.Parser (Parser)
-import Data.Bytes.Types (Bytes(..))
+import Data.Bytes.Types (Bytes (..))
 import Data.Char (ord)
+import Data.Foldable (foldlM)
 import Data.Number.Scientific (Scientific)
-import Data.Primitive (ByteArray(ByteArray),MutableByteArray,SmallArray,Array,PrimArray,Prim)
-import Data.Text.Short (ShortText)
-import GHC.Exts (Char(C#),Int(I#),gtWord#,ltWord#,word2Int#,chr#)
-import GHC.Word (Word8,Word16,Word32,Word64)
-import GHC.Int (Int8,Int16,Int32,Int64)
+import Data.Primitive (Array, ByteArray (ByteArray), MutableByteArray, Prim, PrimArray, SmallArray)
 import Data.Text (Text)
-import Data.Foldable (foldlM)
-import Control.Monad.Trans.Except (runExceptT,except)
-import Control.Monad.Trans.Class (lift)
-import Data.Bytes.Chunks (Chunks)
+import Data.Text.Short (ShortText)
+import GHC.Exts (Char (C#), Int (I#), chr#, gtWord#, ltWord#, word2Int#)
+import GHC.Int (Int16, Int32, Int64, Int8)
+import GHC.Word (Word16, Word32, Word64, Word8)
 
-import qualified Prelude
 import qualified Data.Builder.ST as B
+import qualified Data.ByteString.Short.Internal as BSS
 import qualified Data.Bytes as Bytes
-import qualified Data.Bytes.Chunks as ByteChunks
 import qualified Data.Bytes.Builder as BLDR
+import qualified Data.Bytes.Chunks as ByteChunks
 import qualified Data.Bytes.Parser as P
+import qualified Data.Bytes.Parser.Latin as Latin
+import qualified Data.Bytes.Parser.Unsafe as Unsafe
+import qualified Data.Bytes.Parser.Utf8 as Utf8
 import qualified Data.Chunks as Chunks
-import qualified Data.Text.Short.Unsafe as TS
+import qualified Data.List as List
 import qualified Data.Number.Scientific as SCI
 import qualified Data.Primitive as PM
 import qualified Data.Primitive.Contiguous as Contiguous
-import qualified Data.Bytes.Parser.Utf8 as Utf8
-import qualified Data.Bytes.Parser.Latin as Latin
-import qualified Data.ByteString.Short.Internal as BSS
-import qualified Data.Bytes.Parser.Unsafe as Unsafe
 import qualified Data.Text.Short as TS
-import qualified Data.List as List
+import qualified Data.Text.Short.Unsafe as TS
 import qualified GHC.Word.Compat
+import qualified Prelude
 
--- | The JSON syntax tree described by the ABNF in RFC 7159. Notable
--- design decisions include:
---
--- * @True@ and @False@ are their own data constructors rather than
---   being lumped together under a data constructor for boolean values.
---   This improves performance when decoding the syntax tree to a @Bool@.
--- * @Object@ uses an association list rather than a hash map. This is
---   the data type that key-value pairs can be parsed into most cheaply.
--- * @Object@ and @Array@ both use 'Chunks' rather than using @SmallArray@
---   or cons-list directly. This a middle ground between those two types. We
---   get the efficent use of cache lines that @SmallArray@ offers, and we get
---   the worst-case @O(1)@ appends that cons-list offers. Users will typically
---   fold over the elements with the @Foldable@ instance of 'Chunks', although
---   there are functions in @Data.Chunks@ that efficently perform other
---   operations.
+{- | The JSON syntax tree described by the ABNF in RFC 7159. Notable
+design decisions include:
+
+* @True@ and @False@ are their own data constructors rather than
+  being lumped together under a data constructor for boolean values.
+  This improves performance when decoding the syntax tree to a @Bool@.
+* @Object@ uses an association list rather than a hash map. This is
+  the data type that key-value pairs can be parsed into most cheaply.
+* @Object@ and @Array@ both use 'Chunks' rather than using @SmallArray@
+  or cons-list directly. This a middle ground between those two types. We
+  get the efficent use of cache lines that @SmallArray@ offers, and we get
+  the worst-case @O(1)@ appends that cons-list offers. Users will typically
+  fold over the elements with the @Foldable@ instance of 'Chunks', although
+  there are functions in @Data.Chunks@ that efficently perform other
+  operations.
+-}
 data Value
   = Object !(SmallArray Member)
   | Array !(SmallArray Value)
@@ -131,11 +138,12 @@
   | Null
   | True
   | False
-  deriving stock (Eq,Show)
+  deriving stock (Eq, Show)
 
--- | Exceptions that can happen while parsing JSON. Do not pattern
--- match on values of this type. New data constructors may be added
--- at any time without a major version bump.
+{- | Exceptions that can happen while parsing JSON. Do not pattern
+match on values of this type. New data constructors may be added
+at any time without a major version bump.
+-}
 data SyntaxException
   = EmptyInput
   | ExpectedColon
@@ -155,41 +163,43 @@
   | LeadingZero
   | UnexpectedLeftovers
   | PossibleOverflow
-  deriving stock (Eq,Show)
+  deriving stock (Eq, Show)
   deriving anyclass (Exception)
 
--- | A key-value pair in a JSON object. The name of this type is
--- taken from section 4 of RFC 7159.
+{- | A key-value pair in a JSON object. The name of this type is
+taken from section 4 of RFC 7159.
+-}
 data Member = Member
   { key :: {-# UNPACK #-} !ShortText
   , value :: !Value
-  } deriving stock (Eq,Show)
+  }
+  deriving stock (Eq, Show)
 
 -- | An array with no elements (i.e. @[]@)
 emptyArray :: Value
-{-# noinline emptyArray #-}
+{-# NOINLINE emptyArray #-}
 emptyArray = Array mempty
 
 -- | An object with no members (i.e. @{}@)
 emptyObject :: Value
-{-# noinline emptyObject #-}
+{-# NOINLINE emptyObject #-}
 emptyObject = Object mempty
 
 isSpace :: Word8 -> Prelude.Bool
-{-# inline isSpace #-}
+{-# INLINE isSpace #-}
 isSpace w =
-     w == c2w ' '
-  || w == c2w '\t'
-  || w == c2w '\r'
-  || w == c2w '\n'
+  w == c2w ' '
+    || w == c2w '\t'
+    || w == c2w '\r'
+    || w == c2w '\n'
 
 -- | Decode a JSON syntax tree from a byte sequence.
 decode :: Bytes -> Either SyntaxException Value
-{-# noinline decode #-}
+{-# NOINLINE decode #-}
 decode = P.parseBytesEither parser
 
 parser :: Parser SyntaxException s Value
-{-# inline parser #-}
+{-# INLINE parser #-}
 parser = do
   P.skipWhile isSpace
   result <- Latin.any EmptyInput >>= parserStep
@@ -197,69 +207,73 @@
   P.endOfInput UnexpectedLeftovers
   pure result
 
--- | Decode newline-delimited JSON. Both the LF and the CRLF conventions
--- are supported. The newline character (or character sequence) following
--- the final object may be omitted. This also allows blanks lines consisting
--- of only whitespace.
---
--- It's not strictly necessary for this to be a part of this library, but
--- newline-delimited JSON is somewhat common in practice. It's nice to have
--- this here instead of having to reimplement it in a bunch of different
--- applications.
---
--- Note: To protect against malicious input, this reject byte sequences with
--- more than 10 million newlines. If this is causing a problem for you, open
--- an issue.
---
--- Other note: in the future, this function might be changed transparently
--- to parallelize the decoding of large input (at least 1000 lines) with
--- GHC sparks.
+{- | Decode newline-delimited JSON. Both the LF and the CRLF conventions
+are supported. The newline character (or character sequence) following
+the final object may be omitted. This also allows blanks lines consisting
+of only whitespace.
+
+It's not strictly necessary for this to be a part of this library, but
+newline-delimited JSON is somewhat common in practice. It's nice to have
+this here instead of having to reimplement it in a bunch of different
+applications.
+
+Note: To protect against malicious input, this reject byte sequences with
+more than 10 million newlines. If this is causing a problem for you, open
+an issue.
+
+Other note: in the future, this function might be changed transparently
+to parallelize the decoding of large input (at least 1000 lines) with
+GHC sparks.
+-}
 decodeNewlineDelimited :: Bytes -> Either SyntaxException (SmallArray Value)
-{-# noinline decodeNewlineDelimited #-}
+{-# NOINLINE decodeNewlineDelimited #-}
 decodeNewlineDelimited !everything =
   let maxVals = Bytes.count 0x0A everything + 1
    in if maxVals > 10000000
         then Left PossibleOverflow
         else runST $ runExceptT $ do
           !dst <- PM.newSmallArray maxVals Null
-          !total <- foldlM
-            (\ !ix b ->
-              let clean = Bytes.dropWhile isSpace (Bytes.dropWhileEnd isSpace b)
-               in if Bytes.null clean
-                    then pure ix
-                    else do
-                      v <- except (decode clean)
-                      lift (PM.writeSmallArray dst ix v)
-                      pure (ix + 1)
-            ) 0 (Bytes.split 0x0A everything)
+          !total <-
+            foldlM
+              ( \ !ix b ->
+                  let clean = Bytes.dropWhile isSpace (Bytes.dropWhileEnd isSpace b)
+                   in if Bytes.null clean
+                        then pure ix
+                        else do
+                          v <- except (decode clean)
+                          lift (PM.writeSmallArray dst ix v)
+                          pure (ix + 1)
+              )
+              0
+              (Bytes.split 0x0A everything)
           lift $ PM.shrinkSmallMutableArray dst total
           dst' <- lift $ PM.unsafeFreezeSmallArray dst
           pure dst'
 
 toChunks :: Value -> Chunks
-{-# inline toChunks #-}
+{-# INLINE toChunks #-}
 toChunks = BLDR.run 512 . encode
 
 toBytes :: Value -> Bytes
-{-# inline toBytes #-}
+{-# INLINE toBytes #-}
 toBytes = ByteChunks.concat . toChunks
 
 toByteArray :: Value -> ByteArray
-{-# inline toByteArray #-}
+{-# INLINE toByteArray #-}
 toByteArray = ByteChunks.concatU . toChunks
 
 toShortText :: Value -> ShortText
-{-# inline toShortText #-}
+{-# INLINE toShortText #-}
 toShortText v = case toByteArray v of
   ByteArray x -> TS.fromShortByteStringUnsafe (BSS.SBS x)
 
 toText :: Value -> Text
-{-# inline toText #-}
+{-# INLINE toText #-}
 toText = TS.toText . toShortText
 
 -- | Encode a JSON syntax tree.
 encode :: Value -> BLDR.Builder
-{-# noinline encode #-}
+{-# NOINLINE encode #-}
 encode v0 = BLDR.rebuild $ case v0 of
   True -> BLDR.ascii4 't' 'r' 'u' 'e'
   False -> BLDR.ascii5 'f' 'a' 'l' 's' 'e'
@@ -271,40 +285,39 @@
     _ ->
       let !(# z #) = PM.indexSmallArray## ys 0
        in BLDR.ascii '['
-          <>
-          encode z
-          <>
-          foldrTail
-            ( \v b -> BLDR.ascii ',' <> encode v <> b
-            ) (BLDR.ascii ']') ys
+            <> encode z
+            <> foldrTail
+              ( \v b -> BLDR.ascii ',' <> encode v <> b
+              )
+              (BLDR.ascii ']')
+              ys
   Object ys -> case PM.sizeofSmallArray ys of
     0 -> BLDR.ascii2 '{' '}'
     _ ->
       let !(# z #) = PM.indexSmallArray## ys 0
        in BLDR.ascii '{'
-          <>
-          encodeMember z
-          <>
-          foldrTail
-            ( \v b -> BLDR.ascii ',' <> encodeMember v <> b
-            ) (BLDR.ascii '}') ys
+            <> encodeMember z
+            <> foldrTail
+              ( \v b -> BLDR.ascii ',' <> encodeMember v <> b
+              )
+              (BLDR.ascii '}')
+              ys
 
 encodeMember :: Member -> BLDR.Builder
-encodeMember Member{key,value} =
+encodeMember Member {key, value} =
   BLDR.shortTextJsonString key
-  <>
-  BLDR.ascii ':'
-  <>
-  encode value
+    <> BLDR.ascii ':'
+    <> encode value
 
 foldrTail :: (a -> b -> b) -> b -> PM.SmallArray a -> b
-{-# inline foldrTail #-}
-foldrTail f z !ary = go 1 where
+{-# INLINE foldrTail #-}
+foldrTail f z !ary = go 1
+ where
   !sz = PM.sizeofSmallArray ary
   go i
     | i == sz = z
-    | (# x #) <- PM.indexSmallArray## ary i
-    = f x (go (i+1))
+    | (# x #) <- PM.indexSmallArray## ary i =
+        f x (go (i + 1))
 
 -- Precondition: skip over all space before calling this.
 -- It will not skip leading space for you. It does not skip
@@ -326,15 +339,17 @@
     start <- Unsafe.cursor
     string String start
   '-' -> fmap Number (SCI.parserNegatedUtf8Bytes InvalidNumber)
-  '0' -> Latin.trySatisfy (\c -> c >= '0' && c <= '9') >>= \case
-    Prelude.True -> P.fail LeadingZero
-    Prelude.False -> fmap Number (SCI.parserTrailingUtf8Bytes InvalidNumber 0)
-  c | c >= '1' && c <= '9' ->
+  '0' ->
+    Latin.trySatisfy (\c -> c >= '0' && c <= '9') >>= \case
+      Prelude.True -> P.fail LeadingZero
+      Prelude.False -> fmap Number (SCI.parserTrailingUtf8Bytes InvalidNumber 0)
+  c
+    | c >= '1' && c <= '9' ->
         fmap Number (SCI.parserTrailingUtf8Bytes InvalidNumber (ord c - 48))
   _ -> P.fail InvalidLeader
 
 objectTrailedByBrace :: Parser SyntaxException s Value
-{-# inline objectTrailedByBrace #-}
+{-# INLINE objectTrailedByBrace #-}
 objectTrailedByBrace = do
   P.skipWhile isSpace
   Latin.any IncompleteObject >>= \case
@@ -382,7 +397,7 @@
 --
 -- This parser handles everything after the LBRACKET character.
 arrayTrailedByBracket :: Parser SyntaxException s Value
-{-# inline arrayTrailedByBracket #-}
+{-# INLINE arrayTrailedByBracket #-}
 arrayTrailedByBracket = do
   P.skipWhile isSpace
   Latin.any IncompleteArray >>= \case
@@ -395,7 +410,7 @@
 
 -- From RFC 7159:
 --
--- > value-separator = ws COMMA ws 
+-- > value-separator = ws COMMA ws
 -- > array = begin-array [ value *( value-separator value ) ] end-array
 --
 -- This handles the all values after the first one. That is:
@@ -427,12 +442,14 @@
 -- mark the function as NOINLINE. This would prevent the generated
 -- code from being needlessly duplicated in three different places.
 string :: (ShortText -> a) -> Int -> Parser SyntaxException s a
-{-# inline string #-}
-string wrap !start = go 1 where
+{-# INLINE string #-}
+string wrap !start = go 1
+ where
   go !canMemcpy = do
     P.any IncompleteString >>= \case
       92 -> P.any InvalidEscapeSequence *> go 0 -- backslash
-      34 -> do -- double quote
+      34 -> do
+        -- double quote
         !pos <- Unsafe.cursor
         case canMemcpy of
           1 -> do
@@ -452,46 +469,49 @@
       GHC.Word.Compat.W8# w -> go (canMemcpy .&. I# (ltWord# w 128##) .&. I# (gtWord# w 31##))
 
 copyAndEscape :: (ShortText -> a) -> Int -> Parser SyntaxException s a
-{-# inline copyAndEscape #-}
+{-# INLINE copyAndEscape #-}
 copyAndEscape wrap !maxLen = do
   !dst <- P.effect (PM.newByteArray maxLen)
-  let go !ix = Utf8.any# IncompleteString `P.bindFromCharToLifted` \c -> case c of
-        '\\'# -> Latin.any IncompleteEscapeSequence >>= \case
-          '"' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '"'))
-            go (ix + 1)
-          '\\' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '\\'))
-            go (ix + 1)
-          't' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '\t'))
-            go (ix + 1)
-          'n' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '\n'))
-            go (ix + 1)
-          'r' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '\r'))
-            go (ix + 1)
-          '/' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '/'))
-            go (ix + 1)
-          'b' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '\b'))
-            go (ix + 1)
-          'f' -> do
-            P.effect (PM.writeByteArray dst ix (c2w '\f'))
-            go (ix + 1)
-          'u' -> do
-            w <- Latin.hexFixedWord16 InvalidEscapeSequence
-            if w >= 0xD800 && w < 0xDFFF
-              then go =<< P.effect (encodeUtf8Char dst ix '\xFFFD')
-              else go =<< P.effect (encodeUtf8Char dst ix (w16ToChar w))
-          _ -> P.fail InvalidEscapeSequence
-        '"'# -> do
-          str <- P.effect
-            (PM.unsafeFreezeByteArray =<< PM.resizeMutableByteArray dst ix)
-          pure (wrap (TS.fromShortByteStringUnsafe (byteArrayToShortByteString str)))
-        _ -> go =<< P.effect (encodeUtf8Char dst ix (C# c))
+  let go !ix =
+        Utf8.any# IncompleteString `P.bindFromCharToLifted` \c -> case c of
+          '\\'# ->
+            Latin.any IncompleteEscapeSequence >>= \case
+              '"' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '"'))
+                go (ix + 1)
+              '\\' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '\\'))
+                go (ix + 1)
+              't' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '\t'))
+                go (ix + 1)
+              'n' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '\n'))
+                go (ix + 1)
+              'r' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '\r'))
+                go (ix + 1)
+              '/' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '/'))
+                go (ix + 1)
+              'b' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '\b'))
+                go (ix + 1)
+              'f' -> do
+                P.effect (PM.writeByteArray dst ix (c2w '\f'))
+                go (ix + 1)
+              'u' -> do
+                w <- Latin.hexFixedWord16 InvalidEscapeSequence
+                if w >= 0xD800 && w < 0xDFFF
+                  then go =<< P.effect (encodeUtf8Char dst ix '\xFFFD')
+                  else go =<< P.effect (encodeUtf8Char dst ix (w16ToChar w))
+              _ -> P.fail InvalidEscapeSequence
+          '"'# -> do
+            str <-
+              P.effect
+                (PM.unsafeFreezeByteArray =<< PM.resizeMutableByteArray dst ix)
+            pure (wrap (TS.fromShortByteStringUnsafe (byteArrayToShortByteString str)))
+          _ -> go =<< P.effect (encodeUtf8Char dst ix (C# c))
   go 0
 
 encodeUtf8Char :: MutableByteArray s -> Int -> Char -> ST s Int
@@ -500,27 +520,45 @@
       PM.writeByteArray marr ix (c2w c)
       pure (ix + 1)
   | c < '\x0800' = do
-      PM.writeByteArray marr ix
+      PM.writeByteArray
+        marr
+        ix
         (fromIntegral @Int @Word8 (unsafeShiftR (ord c) 6 .|. 0b11000000))
-      PM.writeByteArray marr (ix + 1)
+      PM.writeByteArray
+        marr
+        (ix + 1)
         (0b10000000 .|. (0b00111111 .&. (fromIntegral @Int @Word8 (ord c))))
       pure (ix + 2)
   | c <= '\xffff' = do
-      PM.writeByteArray marr ix
+      PM.writeByteArray
+        marr
+        ix
         (fromIntegral @Int @Word8 (unsafeShiftR (ord c) 12 .|. 0b11100000))
-      PM.writeByteArray marr (ix + 1)
+      PM.writeByteArray
+        marr
+        (ix + 1)
         (0b10000000 .|. (0b00111111 .&. (fromIntegral @Int @Word8 (unsafeShiftR (ord c) 6))))
-      PM.writeByteArray marr (ix + 2)
+      PM.writeByteArray
+        marr
+        (ix + 2)
         (0b10000000 .|. (0b00111111 .&. (fromIntegral @Int @Word8 (ord c))))
       pure (ix + 3)
   | otherwise = do
-      PM.writeByteArray marr ix
+      PM.writeByteArray
+        marr
+        ix
         (fromIntegral @Int @Word8 (unsafeShiftR (ord c) 18 .|. 0b11110000))
-      PM.writeByteArray marr (ix + 1)
+      PM.writeByteArray
+        marr
+        (ix + 1)
         (0b10000000 .|. (0b00111111 .&. (fromIntegral @Int @Word8 (unsafeShiftR (ord c) 12))))
-      PM.writeByteArray marr (ix + 2)
+      PM.writeByteArray
+        marr
+        (ix + 2)
         (0b10000000 .|. (0b00111111 .&. (fromIntegral @Int @Word8 (unsafeShiftR (ord c) 6))))
-      PM.writeByteArray marr (ix + 3)
+      PM.writeByteArray
+        marr
+        (ix + 3)
         (0b10000000 .|. (0b00111111 .&. (fromIntegral @Int @Word8 (ord c))))
       pure (ix + 4)
 
@@ -533,100 +571,118 @@
 
 -- | Infix pattern synonym for 'Member'.
 pattern (:->) :: ShortText -> Value -> Member
-pattern key :-> value = Member{key,value}
+pattern key :-> value = Member {key, value}
 
--- | Construct a JSON array from a list of JSON values.
---
--- Unlike 'objectFromList', this is not currently equipped with a
--- rewrite rule.
+{- | Construct a JSON array from a list of JSON values.
+
+Unlike 'objectFromList', this is not currently equipped with a
+rewrite rule.
+-}
 arrayFromList :: [Value] -> Value
 arrayFromList ms = Array $ PM.smallArrayFromList ms
 
--- | Construct a JSON object from a list of members.
---
--- Note: When the argument is a list literal with 16 or fewer elements,
--- a rewrite rule transforms this into the appropriate @objectN@ function.
--- When the argument is not a list literal, this function just calls
--- @smallArrayFromList@ on the members, which has poor performance.
+{- | Construct a JSON object from a list of members.
+
+Note: When the argument is a list literal with 16 or fewer elements,
+a rewrite rule transforms this into the appropriate @objectN@ function.
+When the argument is not a list literal, this function just calls
+@smallArrayFromList@ on the members, which has poor performance.
+-}
 objectFromList :: [Member] -> Value
 objectFromList ms = Object $ PM.smallArrayFromList ms
-
 {-# NOINLINE objectFromList #-}
-{-# RULES "objectFromList/1" forall a.
-      objectFromList (a : []) =
-      object1 a
-#-}
-{-# RULES "objectFromList/2" forall a b.
-      objectFromList (a : b : []) =
-      object2 a b
-#-}
-{-# RULES "objectFromList/3" forall a b c.
-      objectFromList (a : b : c : []) =
-      object3 a b c
-#-}
-{-# RULES "objectFromList/4" forall a b c d.
-      objectFromList (a : b : c : d : []) =
-      object4 a b c d
-#-}
-{-# RULES "objectFromList/5" forall a b c d e.
-      objectFromList (a : b : c : d : e : []) =
-      object5 a b c d e
-#-}
-{-# RULES "objectFromList/6" forall a b c d e f.
-      objectFromList (a : b : c : d : e : f : []) =
-      object6 a b c d e f
-#-}
-{-# RULES "objectFromList/7" forall a b c d e f g.
-      objectFromList (a : b : c : d : e : f : g : []) =
-      object7 a b c d e f g
-#-}
-{-# RULES "objectFromList/8" forall a b c d e f g h.
-      objectFromList (a : b : c : d : e : f : g : h : []) =
-      object8 a b c d e f g h
-#-}
-{-# RULES "objectFromList/9" forall a b c d e f g h i.
-      objectFromList (a : b : c : d : e : f : g : h : i : []) =
-      object9 a b c d e f g h i
-#-}
-{-# RULES "objectFromList/10" forall a b c d e f g h i j.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : []) =
-      object10 a b c d e f g h i j
-#-}
-{-# RULES "objectFromList/11" forall a b c d e f g h i j k.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : k : []) =
-      object11 a b c d e f g h i j k
-#-}
-{-# RULES "objectFromList/12" forall a b c d e f g h i j k l.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : []) =
-      object12 a b c d e f g h i j k l
-#-}
-{-# RULES "objectFromList/13" forall a b c d e f g h i j k l m.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : []) =
-      object13 a b c d e f g h i j k l m
-#-}
-{-# RULES "objectFromList/14" forall a b c d e f g h i j k l m n.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : n : []) =
-      object14 a b c d e f g h i j k l m n
-#-}
-{-# RULES "objectFromList/15" forall a b c d e f g h i j k l m n o.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : n : o : []) =
-      object15 a b c d e f g h i j k l m n o
-#-}
-{-# RULES "objectFromList/16" forall a b c d e f g h i j k l m n o p.
-      objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : n : o : p : []) =
-      object16 a b c d e f g h i j k l m n o p
-#-}
 
+{-# RULES
+"objectFromList/1" forall a.
+  objectFromList (a : []) =
+    object1 a
+  #-}
+{-# RULES
+"objectFromList/2" forall a b.
+  objectFromList (a : b : []) =
+    object2 a b
+  #-}
+{-# RULES
+"objectFromList/3" forall a b c.
+  objectFromList (a : b : c : []) =
+    object3 a b c
+  #-}
+{-# RULES
+"objectFromList/4" forall a b c d.
+  objectFromList (a : b : c : d : []) =
+    object4 a b c d
+  #-}
+{-# RULES
+"objectFromList/5" forall a b c d e.
+  objectFromList (a : b : c : d : e : []) =
+    object5 a b c d e
+  #-}
+{-# RULES
+"objectFromList/6" forall a b c d e f.
+  objectFromList (a : b : c : d : e : f : []) =
+    object6 a b c d e f
+  #-}
+{-# RULES
+"objectFromList/7" forall a b c d e f g.
+  objectFromList (a : b : c : d : e : f : g : []) =
+    object7 a b c d e f g
+  #-}
+{-# RULES
+"objectFromList/8" forall a b c d e f g h.
+  objectFromList (a : b : c : d : e : f : g : h : []) =
+    object8 a b c d e f g h
+  #-}
+{-# RULES
+"objectFromList/9" forall a b c d e f g h i.
+  objectFromList (a : b : c : d : e : f : g : h : i : []) =
+    object9 a b c d e f g h i
+  #-}
+{-# RULES
+"objectFromList/10" forall a b c d e f g h i j.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : []) =
+    object10 a b c d e f g h i j
+  #-}
+{-# RULES
+"objectFromList/11" forall a b c d e f g h i j k.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : k : []) =
+    object11 a b c d e f g h i j k
+  #-}
+{-# RULES
+"objectFromList/12" forall a b c d e f g h i j k l.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : []) =
+    object12 a b c d e f g h i j k l
+  #-}
+{-# RULES
+"objectFromList/13" forall a b c d e f g h i j k l m.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : []) =
+    object13 a b c d e f g h i j k l m
+  #-}
+{-# RULES
+"objectFromList/14" forall a b c d e f g h i j k l m n.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : n : []) =
+    object14 a b c d e f g h i j k l m n
+  #-}
+{-# RULES
+"objectFromList/15" forall a b c d e f g h i j k l m n o.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : n : o : []) =
+    object15 a b c d e f g h i j k l m n o
+  #-}
+{-# RULES
+"objectFromList/16" forall a b c d e f g h i j k l m n o p.
+  objectFromList (a : b : c : d : e : f : g : h : i : j : k : l : m : n : o : p : []) =
+    object16 a b c d e f g h i j k l m n o p
+  #-}
+
 -- | Construct a JSON object with one member.
 object1 :: Member -> Value
-{-# inline object1 #-}
+{-# INLINE object1 #-}
 object1 a = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 1 a
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with two members.
 object2 :: Member -> Member -> Value
-{-# inline object2 #-}
+{-# INLINE object2 #-}
 object2 a b = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 2 a
   PM.writeSmallArray dst 1 b
@@ -634,7 +690,7 @@
 
 -- | Construct a JSON object with three members.
 object3 :: Member -> Member -> Member -> Value
-{-# inline object3 #-}
+{-# INLINE object3 #-}
 object3 a b c = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 3 a
   PM.writeSmallArray dst 1 b
@@ -643,7 +699,7 @@
 
 -- | Construct a JSON object with four members.
 object4 :: Member -> Member -> Member -> Member -> Value
-{-# inline object4 #-}
+{-# INLINE object4 #-}
 object4 a b c d = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 4 a
   PM.writeSmallArray dst 1 b
@@ -653,7 +709,7 @@
 
 -- | Construct a JSON object with five members.
 object5 :: Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object5 #-}
+{-# INLINE object5 #-}
 object5 a b c d e = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 5 a
   PM.writeSmallArray dst 1 b
@@ -664,7 +720,7 @@
 
 -- | Construct a JSON object with six members.
 object6 :: Member -> Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object6 #-}
+{-# INLINE object6 #-}
 object6 a b c d e f = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 6 a
   PM.writeSmallArray dst 1 b
@@ -676,7 +732,7 @@
 
 -- | Construct a JSON object with seven members.
 object7 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object7 #-}
+{-# INLINE object7 #-}
 object7 a b c d e f g = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 7 a
   PM.writeSmallArray dst 1 b
@@ -689,7 +745,7 @@
 
 -- | Construct a JSON object with nine members.
 object8 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object8 #-}
+{-# INLINE object8 #-}
 object8 a b c d e f g h = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 8 a
   PM.writeSmallArray dst 1 b
@@ -702,9 +758,18 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with nine members.
-object9 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-        -> Value
-{-# inline object9 #-}
+object9 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object9 #-}
 object9 a b c d e f g h i = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 9 a
   PM.writeSmallArray dst 1 b
@@ -718,9 +783,19 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with ten members.
-object10 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member 
-         -> Member -> Member -> Value
-{-# inline object10 #-}
+object10 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object10 #-}
 object10 a b c d e f g h i j = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 10 a
   PM.writeSmallArray dst 1 b
@@ -735,9 +810,20 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with eleven members.
-object11 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Member -> Member -> Member -> Value
-{-# inline object11 #-}
+object11 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object11 #-}
 object11 a b c d e f g h i j k = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 11 a
   PM.writeSmallArray dst 1 b
@@ -753,9 +839,21 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with twelve members.
-object12 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Member -> Member -> Member -> Member -> Value
-{-# inline object12 #-}
+object12 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object12 #-}
 object12 a b c d e f g h i j k l = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 12 a
   PM.writeSmallArray dst 1 b
@@ -772,9 +870,22 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with thirteen members.
-object13 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object13 #-}
+object13 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object13 #-}
 object13 a b c d e f g h i j k l m = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 13 a
   PM.writeSmallArray dst 1 b
@@ -792,9 +903,23 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with fourteen members.
-object14 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Member -> Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object14 #-}
+object14 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object14 #-}
 object14 a b c d e f g h i j k l m n = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 14 a
   PM.writeSmallArray dst 1 b
@@ -813,9 +938,24 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with fifteen members.
-object15 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
-{-# inline object15 #-}
+object15 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object15 #-}
 object15 a b c d e f g h i j k l m n o = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 15 a
   PM.writeSmallArray dst 1 b
@@ -835,10 +975,25 @@
   PM.unsafeFreezeSmallArray dst
 
 -- | Construct a JSON object with sixteen members.
-object16 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
-         -> Value
-{-# inline object16 #-}
+object16 ::
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Member ->
+  Value
+{-# INLINE object16 #-}
 object16 a b c d e f g h i j k l m n o p = Object $ runSmallArrayST $ do
   dst <- PM.newSmallArray 16 a
   PM.writeSmallArray dst 1 b
@@ -859,51 +1014,51 @@
   PM.unsafeFreezeSmallArray dst
 
 word8 :: Word8 -> Json.Value
-{-# inline word8 #-}
+{-# INLINE word8 #-}
 word8 = Json.Number . SCI.fromWord8
 
 word16 :: Word16 -> Json.Value
-{-# inline word16 #-}
+{-# INLINE word16 #-}
 word16 = Json.Number . SCI.fromWord16
 
 word32 :: Word32 -> Json.Value
-{-# inline word32 #-}
+{-# INLINE word32 #-}
 word32 = Json.Number . SCI.fromWord32
 
 word64 :: Word64 -> Json.Value
-{-# inline word64 #-}
+{-# INLINE word64 #-}
 word64 = Json.Number . SCI.fromWord64
 
 int8 :: Int8 -> Json.Value
-{-# inline int8 #-}
+{-# INLINE int8 #-}
 int8 = Json.Number . SCI.fromInt8
 
 int16 :: Int16 -> Json.Value
-{-# inline int16 #-}
+{-# INLINE int16 #-}
 int16 = Json.Number . SCI.fromInt16
 
 int32 :: Int32 -> Json.Value
-{-# inline int32 #-}
+{-# INLINE int32 #-}
 int32 = Json.Number . SCI.fromInt32
 
 int64 :: Int64 -> Json.Value
-{-# inline int64 #-}
+{-# INLINE int64 #-}
 int64 = Json.Number . SCI.fromInt64
 
 int :: Int -> Json.Value
-{-# inline int #-}
+{-# INLINE int #-}
 int = Json.Number . SCI.fromInt
 
 text :: Text -> Json.Value
-{-# inline text #-}
+{-# INLINE text #-}
 text = Json.String . TS.fromText
 
 shortText :: ShortText -> Json.Value
-{-# inline shortText #-}
+{-# INLINE shortText #-}
 shortText = String
 
 bool :: Prelude.Bool -> Json.Value
-{-# inline bool #-}
+{-# INLINE bool #-}
 bool Prelude.True = True
 bool _ = False
 
@@ -912,25 +1067,26 @@
   toValue :: a -> Value
 
 -- | Encodes the unit value as JSON @null@.
-instance ToValue () where {toValue _ = Null}
-instance ToValue Value where {toValue = id}
-instance ToValue Scientific where {toValue = Number}
-instance ToValue Int where {toValue = int}
-instance ToValue Int8 where {toValue = int8}
-instance ToValue Int16 where {toValue = int16}
-instance ToValue Int32 where {toValue = int32}
-instance ToValue Int64 where {toValue = int64}
-instance ToValue Word8 where {toValue = word8}
-instance ToValue Word16 where {toValue = word16}
-instance ToValue Word32 where {toValue = word32}
-instance ToValue Word64 where {toValue = word64}
-instance ToValue ShortText where {toValue = shortText}
-instance ToValue Text where {toValue = text}
-instance ToValue Prelude.Bool where {toValue = bool}
+instance ToValue () where toValue _ = Null
+
+instance ToValue Value where toValue = id
+instance ToValue Scientific where toValue = Number
+instance ToValue Int where toValue = int
+instance ToValue Int8 where toValue = int8
+instance ToValue Int16 where toValue = int16
+instance ToValue Int32 where toValue = int32
+instance ToValue Int64 where toValue = int64
+instance ToValue Word8 where toValue = word8
+instance ToValue Word16 where toValue = word16
+instance ToValue Word32 where toValue = word32
+instance ToValue Word64 where toValue = word64
+instance ToValue ShortText where toValue = shortText
+instance ToValue Text where toValue = text
+instance ToValue Prelude.Bool where toValue = bool
 instance ToValue Word where
- toValue = word64 . fromIntegral @Word @Word64
+  toValue = word64 . fromIntegral @Word @Word64
 
-instance ToValue a => ToValue [a] where
+instance (ToValue a) => ToValue [a] where
   toValue !xs = runST $ do
     let len = List.length xs
     dst <- PM.newSmallArray len Null
@@ -943,10 +1099,10 @@
             go (ix + 1) zs
     go 0 xs
 
-instance ToValue a => ToValue (SmallArray a) where
+instance (ToValue a) => ToValue (SmallArray a) where
   toValue !xs = Json.Array $! Contiguous.map' toValue xs
 
-instance ToValue a => ToValue (Array a) where
+instance (ToValue a) => ToValue (Array a) where
   toValue !xs = Json.Array $! Contiguous.map' toValue xs
 
 instance (Prim a, ToValue a) => ToValue (PrimArray a) where
diff --git a/src/Json/Flatten.hs b/src/Json/Flatten.hs
--- a/src/Json/Flatten.hs
+++ b/src/Json/Flatten.hs
@@ -1,9 +1,10 @@
-{-# language BangPatterns #-}
-{-# language DuplicateRecordFields #-}
-{-# language NamedFieldPuns #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE NamedFieldPuns #-}
 
--- | Flatten nested JSON objects into a single JSON object in which the keys
--- have been joined by the separator.
+{- | Flatten nested JSON objects into a single JSON object in which the keys
+have been joined by the separator.
+-}
 module Json.Flatten
   ( flatten
   ) where
@@ -11,45 +12,46 @@
 import Control.Monad.ST (ST)
 import Control.Monad.ST.Run (runByteArrayST)
 import Data.Builder.Catenable (Builder)
-import Data.ByteString.Short.Internal (ShortByteString(SBS))
-import Data.Text.Short (ShortText)
-import Data.Primitive (SmallArray,ByteArray(ByteArray),MutableByteArray)
-import Data.Word (Word8)
-import Json (Member(Member))
-import qualified Json
-import qualified Data.Chunks as Chunks
-import qualified Data.Primitive.Contiguous as C
+import qualified Data.Builder.Catenable as Builder
+import Data.ByteString.Short.Internal (ShortByteString (SBS))
 import qualified Data.Bytes as Bytes
 import qualified Data.Bytes.Text.Utf8 as Utf8
+import qualified Data.Chunks as Chunks
+import Data.Primitive (ByteArray (ByteArray), MutableByteArray, SmallArray)
 import qualified Data.Primitive as PM
-import qualified Data.Builder.Catenable as Builder
+import qualified Data.Primitive.Contiguous as C
+import Data.Text.Short (ShortText)
 import qualified Data.Text.Short as TS
 import qualified Data.Text.Short.Unsafe as TS
+import Data.Word (Word8)
+import Json (Member (Member))
+import qualified Json
 
--- | Flatten a json value, recursively descending into objects and joining
--- keys with the separator. For example:
---
--- > { "name": "bilbo"
--- > , "occupation":
--- >   { "name": "burglar"
--- >   , "start": "2022-05-30"
--- >   }
--- > , "height": 124
--- > , "favorites": ["adventures","lunch"]
--- > }
---
--- Becomes:
---
--- > { "name": "bilbo"
--- > , "occupation.name": "burglar"
--- > , "occupation.start": "2022-05-30"
--- > , "height": 124
--- > , "favorites": ["adventures","lunch"]
--- > }
---
--- Currently, the implementation of this function throws an exception if
--- any separator other than period is used. This may be corrected in a future
--- release.
+{- | Flatten a json value, recursively descending into objects and joining
+keys with the separator. For example:
+
+> { "name": "bilbo"
+> , "occupation":
+>   { "name": "burglar"
+>   , "start": "2022-05-30"
+>   }
+> , "height": 124
+> , "favorites": ["adventures","lunch"]
+> }
+
+Becomes:
+
+> { "name": "bilbo"
+> , "occupation.name": "burglar"
+> , "occupation.start": "2022-05-30"
+> , "height": 124
+> , "favorites": ["adventures","lunch"]
+> }
+
+Currently, the implementation of this function throws an exception if
+any separator other than period is used. This may be corrected in a future
+release.
+-}
 flatten :: Char -> Json.Value -> Json.Value
 flatten c v = case c of
   '.' -> flattenPeriod v
@@ -63,7 +65,7 @@
 flattenPeriod :: Json.Value -> Json.Value
 flattenPeriod x = case x of
   Json.Object mbrs ->
-    let bldr = foldMap (\Member{key,value} -> flattenPrefix (ShortTextsBase key) value) mbrs
+    let bldr = foldMap (\Member {key, value} -> flattenPrefix (ShortTextsBase key) value) mbrs
         chunks = Builder.run bldr
         result = Chunks.concat chunks
      in Json.Object result
@@ -71,25 +73,27 @@
   _ -> x
 
 flattenPrefix ::
-     ShortTexts -- context accumulator
-  -> Json.Value
-  -> Builder Json.Member
+  ShortTexts -> -- context accumulator
+  Json.Value ->
+  Builder Json.Member
 flattenPrefix !pre x = case x of
   Json.Object mbrs -> flattenObject pre mbrs
   _ ->
     let !a = flattenPeriod x
         !k = runShortTexts pre
-        !mbr = Json.Member{key=k,value=a}
+        !mbr = Json.Member {key = k, value = a}
      in Builder.Cons mbr Builder.Empty
 
 flattenObject :: ShortTexts -> SmallArray Json.Member -> Builder Json.Member
-flattenObject !pre !mbrs = foldMap
-  (\Member{key,value} -> flattenPrefix (ShortTextsCons key pre) value
-  ) mbrs
+flattenObject !pre !mbrs =
+  foldMap
+    ( \Member {key, value} -> flattenPrefix (ShortTextsCons key pre) value
+    )
+    mbrs
 
 runShortTexts :: ShortTexts -> ShortText
 runShortTexts !ts0 = go 0 ts0
-  where
+ where
   paste :: MutableByteArray s -> Int -> ShortTexts -> ST s ByteArray
   paste !dst !ix (ShortTextsBase t) =
     let len = Bytes.length (Utf8.fromShortText t)
@@ -116,6 +120,6 @@
      in TS.fromShortByteStringUnsafe (SBS r)
 
 st2ba :: ShortText -> ByteArray
-{-# inline st2ba #-}
+{-# INLINE st2ba #-}
 st2ba t = case TS.toShortByteString t of
   SBS x -> ByteArray x
diff --git a/src/Json/Smile.hs b/src/Json/Smile.hs
--- a/src/Json/Smile.hs
+++ b/src/Json/Smile.hs
@@ -10,45 +10,62 @@
 module Json.Smile
   ( -- * Encode JSON Document
     encode
+
     -- * Encode JSON Atoms
+
     -- ** Integer
   , encodeBigInteger
+
     -- ** String
   , encodeString
   , encodeAsciiString
+
     -- ** Key
   , encodeKey
   , encodeAsciiKey
   ) where
 
-import Prelude hiding (Bool(..))
+import Prelude hiding (Bool (..))
 
 import Control.Monad.ST (ST)
 import Control.Monad.ST.Run (runByteArrayST)
-import Data.Bits (countLeadingZeros,complement,unsafeShiftR,(.&.),(.|.))
-import Data.Bits (testBit)
+import Data.Bits
+  ( complement
+  , countLeadingZeros
+  , testBit
+  , unsafeShiftR
+  , (.&.)
+  , (.|.)
+  )
 import Data.Bytes.Builder (Builder)
 import Data.Int (Int32)
-import Data.Primitive (ByteArray,newByteArray)
-import Data.Primitive (writeByteArray,byteArrayFromListN,sizeofByteArray)
-import Data.Primitive (MutableByteArray(..),unsafeFreezeByteArray)
-import Data.Primitive (readByteArray,copyMutableByteArray)
+import Data.Primitive
+  ( ByteArray
+  , MutableByteArray (..)
+  , byteArrayFromListN
+  , copyMutableByteArray
+  , newByteArray
+  , readByteArray
+  , sizeofByteArray
+  , unsafeFreezeByteArray
+  , writeByteArray
+  )
 import Data.Text.Short (ShortText)
-import Data.Word (Word8,Word32,Word64)
-import Data.Word.Zigzag (toZigzag32,toZigzag64)
-import GHC.Exts (RealWorld,Word#,State#)
-import GHC.IO (IO(IO))
-import GHC.Word (Word(..))
-import Json (Value(..), Member(..))
+import Data.Word (Word32, Word64, Word8)
+import Data.Word.Zigzag (toZigzag32, toZigzag64)
+import GHC.Exts (RealWorld, State#, Word#)
+import GHC.IO (IO (IO))
+import GHC.Word (Word (..))
+import Json (Member (..), Value (..))
 import Numeric.Natural (Natural)
 import System.IO.Unsafe (unsafeDupablePerformIO)
 
 import qualified Arithmetic.Nat as Nat
+import qualified Data.ByteString.Short as SBS
 import qualified Data.Bytes as Bytes
 import qualified Data.Bytes.Builder as B
 import qualified Data.Bytes.Builder.Bounded as Bounded
 import qualified Data.Bytes.Builder.Bounded.Unsafe as Unsafe
-import qualified Data.ByteString.Short as SBS
 import qualified Data.Number.Scientific as Sci
 import qualified Data.Text.Short as TS
 import qualified GHC.Exts as Exts
@@ -56,10 +73,11 @@
 import qualified GHC.Num.Integer as Integer
 import qualified Prelude
 
--- | Encode a Json 'Value' to the Smile binary format.
--- This encoder does not produce backreferences.
+{- | Encode a Json 'Value' to the Smile binary format.
+This encoder does not produce backreferences.
+-}
 encode :: Value -> Builder
-{-# inline encode #-}
+{-# INLINE encode #-}
 encode v0 = B.ascii4 ':' ')' '\n' '\x00' <> encodeNoHeader v0
 
 -- The "rebuild" trick was adapted from the fast-builder library. It
@@ -67,25 +85,23 @@
 -- This function is marked noinline to ensure that its performance is
 -- stable.
 encodeNoHeader :: Value -> Builder
-{-# noinline encodeNoHeader #-}
+{-# NOINLINE encodeNoHeader #-}
 encodeNoHeader val = B.rebuild $ case val of
   Object obj ->
     B.word8 0xFA
-    <>
-    foldMap (\Member{key,value} -> encodeKey key <> encodeNoHeader value) obj
-    <>
-    B.word8 0xFB
+      <> foldMap (\Member {key, value} -> encodeKey key <> encodeNoHeader value) obj
+      <> B.word8 0xFB
   Array arr -> B.word8 0xF8 <> foldMap encodeNoHeader arr <> B.word8 0xF9
   String str -> encodeString str
   Number x
     | Just i32 <- Sci.toInt32 x
     , -16 <= i32 && i32 <= 15
-    , w5 <- fromIntegral @Word32 @Word8 (toZigzag32 i32)
-      -> B.word8 (0xC0 + w5)
-    | Just i32 <- Sci.toInt32 x
-      -> B.fromBounded Nat.constant (Bounded.word8 0x24 `Bounded.append` vlqSmile64 (fromIntegral @Word32 @Word64 (toZigzag32 i32)))
-    | Just i64 <- Sci.toInt64 x
-      -> B.fromBounded Nat.constant (Bounded.word8 0x25 `Bounded.append` vlqSmile64 (toZigzag64 i64))
+    , w5 <- fromIntegral @Word32 @Word8 (toZigzag32 i32) ->
+        B.word8 (0xC0 + w5)
+    | Just i32 <- Sci.toInt32 x ->
+        B.fromBounded Nat.constant (Bounded.word8 0x24 `Bounded.append` vlqSmile64 (fromIntegral @Word32 @Word64 (toZigzag32 i32)))
+    | Just i64 <- Sci.toInt64 x ->
+        B.fromBounded Nat.constant (Bounded.word8 0x25 `Bounded.append` vlqSmile64 (toZigzag64 i64))
     | otherwise -> Sci.withExposed encodeSmallDecimal encodeBigDecimal x
   Null -> B.word8 0x21
   False -> B.word8 0x22
@@ -97,12 +113,15 @@
 encodeBigDecimal :: Integer -> Integer -> Builder
 encodeBigDecimal c e = case e of
   0 -> encodeBigInteger c
-  _ -> B.word8 0x2A -- bigdecimal token tag
-    <> vlqSmile ( fromIntegral @Word32 @Natural
-                $ toZigzag32 scale)
-    <> vlqSmile (fromIntegral @Int @Natural $ sizeofByteArray raw) -- size of byte digits
-    <> B.sevenEightSmile (Bytes.fromByteArray raw) -- 7/8 encoding of byte digits
-    where
+  _ ->
+    B.word8 0x2A -- bigdecimal token tag
+      <> vlqSmile
+        ( fromIntegral @Word32 @Natural $
+            toZigzag32 scale
+        )
+      <> vlqSmile (fromIntegral @Int @Natural $ sizeofByteArray raw) -- size of byte digits
+      <> B.sevenEightSmile (Bytes.fromByteArray raw) -- 7/8 encoding of byte digits
+   where
     scale :: Int32
     -- WARNING smile can't handle exponents outside int32_t, so this truncates
     -- WARNING "scale" is what Java BigDecimal thinks, which is
@@ -112,68 +131,73 @@
 
 -- | Encode a number using as SMILE @BigInteger@ token type (prefix @0x26@).
 encodeBigInteger :: Integer -> Builder
-encodeBigInteger n = B.word8 0x26
-  <> vlqSmile (fromIntegral @Int @Natural $ sizeofByteArray raw) -- size of byte digits
-  <> B.sevenEightSmile (Bytes.fromByteArray raw) -- 7/8 encoding of byte digits
-  where
+encodeBigInteger n =
+  B.word8 0x26
+    <> vlqSmile (fromIntegral @Int @Natural $ sizeofByteArray raw) -- size of byte digits
+    <> B.sevenEightSmile (Bytes.fromByteArray raw) -- 7/8 encoding of byte digits
+ where
   !raw = integerToBase256ByteArray n
 
 integerToBase256ByteArray :: Integer -> ByteArray
-integerToBase256ByteArray c = if c == 0
-  then byteArrayFromListN 1 [0::Word8]
-  else case c of
-    Integer.IP bn -> unsafeDupablePerformIO $ do
-      let nDigits256 = fromIntegral @Word @Int (W# (BN.bigNatSizeInBase# 256## bn))
-      mut <- newByteArray nDigits256
-      let !(MutableByteArray mut#) = mut
-      !_ <- liftWordIO (BN.bigNatToMutableByteArray# bn mut# 0## 1# )
-      -- This is safe because Jp cannot have zero inside it.
-      w0 :: Word8 <- readByteArray mut 0
-      if testBit w0 7
-        then do
-          -- If the upper bit is 1, then we must introduce a leading
-          -- zero byte.
-          dst <- newByteArray (nDigits256 + 1)
-          writeByteArray dst 0 (0x00 :: Word8)
-          copyMutableByteArray dst 1 mut 0 nDigits256
-          unsafeFreezeByteArray dst
-        else unsafeFreezeByteArray mut
-    Integer.IN bn -> twosComplementBigNat bn
-    Integer.IS i -> case i Exts.># 0# of
-      1# -> encodePosWordBase256 (W# (Exts.int2Word# i))
-      _ -> encodeNegWordBase256 (W# (Exts.int2Word# i))
+integerToBase256ByteArray c =
+  if c == 0
+    then byteArrayFromListN 1 [0 :: Word8]
+    else case c of
+      Integer.IP bn -> unsafeDupablePerformIO $ do
+        let nDigits256 = fromIntegral @Word @Int (W# (BN.bigNatSizeInBase# 256## bn))
+        mut <- newByteArray nDigits256
+        let !(MutableByteArray mut#) = mut
+        !_ <- liftWordIO (BN.bigNatToMutableByteArray# bn mut# 0## 1#)
+        -- This is safe because Jp cannot have zero inside it.
+        w0 :: Word8 <- readByteArray mut 0
+        if testBit w0 7
+          then do
+            -- If the upper bit is 1, then we must introduce a leading
+            -- zero byte.
+            dst <- newByteArray (nDigits256 + 1)
+            writeByteArray dst 0 (0x00 :: Word8)
+            copyMutableByteArray dst 1 mut 0 nDigits256
+            unsafeFreezeByteArray dst
+          else unsafeFreezeByteArray mut
+      Integer.IN bn -> twosComplementBigNat bn
+      Integer.IS i -> case i Exts.># 0# of
+        1# -> encodePosWordBase256 (W# (Exts.int2Word# i))
+        _ -> encodeNegWordBase256 (W# (Exts.int2Word# i))
 
 liftWordIO :: (State# RealWorld -> (# State# RealWorld, Word# #)) -> IO Word
-{-# inline liftWordIO #-}
-liftWordIO f = IO
-  (\s -> case f s of
-    (# s', w #) -> (# s', W# w #)
-  )
+{-# INLINE liftWordIO #-}
+liftWordIO f =
+  IO
+    ( \s -> case f s of
+        (# s', w #) -> (# s', W# w #)
+    )
 
 twosComplementBigNat :: BN.BigNat# -> ByteArray
 twosComplementBigNat bn = unsafeDupablePerformIO $ do
   let nDigits256 = fromIntegral @Word @Int (W# (BN.bigNatSizeInBase# 256## bn))
   mut <- newByteArray nDigits256
   let !(MutableByteArray mut#) = mut
-  !_ <- liftWordIO (BN.bigNatToMutableByteArray# bn mut# 0## 1# )
+  !_ <- liftWordIO (BN.bigNatToMutableByteArray# bn mut# 0## 1#)
   -- First, complement
-  let goComplement !ix = if ix >= 0
-        then do
-          w :: Word8 <- readByteArray mut ix
-          writeByteArray mut ix (complement w)
-          goComplement (ix - 1)
-        else pure ()
+  let goComplement !ix =
+        if ix >= 0
+          then do
+            w :: Word8 <- readByteArray mut ix
+            writeByteArray mut ix (complement w)
+            goComplement (ix - 1)
+          else pure ()
   goComplement (nDigits256 - 1)
   -- Second, add one
-  let goAddOne !ix = if ix >= 0
-        then do
-          w :: Word8 <- readByteArray mut ix
-          case w of
-            0xFF -> do
-              writeByteArray mut ix (0 :: Word8)
-              goAddOne (ix - 1)
-            _ -> writeByteArray mut ix (w + 1)
-        else pure ()
+  let goAddOne !ix =
+        if ix >= 0
+          then do
+            w :: Word8 <- readByteArray mut ix
+            case w of
+              0xFF -> do
+                writeByteArray mut ix (0 :: Word8)
+                goAddOne (ix - 1)
+              _ -> writeByteArray mut ix (w + 1)
+          else pure ()
   goAddOne (nDigits256 - 1)
   leader :: Word8 <- readByteArray mut 0
   if testBit leader 7
@@ -201,11 +225,12 @@
   -- Because the latter would be misinterpreted as a negative number.
   let !total = quot (72 - countLeadingZeros w) 8
   dst <- newByteArray total
-  let go !ix !acc = if ix >= 0 
-        then do
-          writeByteArray dst ix (fromIntegral @Word @Word8 acc)
-          go (ix - 1) (unsafeShiftR acc 8)
-        else unsafeFreezeByteArray dst
+  let go !ix !acc =
+        if ix >= 0
+          then do
+            writeByteArray dst ix (fromIntegral @Word @Word8 acc)
+            go (ix - 1) (unsafeShiftR acc 8)
+          else unsafeFreezeByteArray dst
   go (total - 1) w
 
 -- Same deal as encodePosWordBase256.
@@ -215,22 +240,24 @@
 encodeNegWordBase256 !w = runByteArrayST $ do
   let !total = quot (72 - countLeadingZeros (complement w)) 8
   dst <- newByteArray total
-  let go !ix !acc = if ix >= 0 
-        then do
-          writeByteArray dst ix (fromIntegral @Word @Word8 acc)
-          go (ix - 1) (unsafeShiftR acc 8)
-        else unsafeFreezeByteArray dst
+  let go !ix !acc =
+        if ix >= 0
+          then do
+            writeByteArray dst ix (fromIntegral @Word @Word8 acc)
+            go (ix - 1) (unsafeShiftR acc 8)
+          else unsafeFreezeByteArray dst
   go (total - 1) w
 
--- | Encode a string in which all characters are ASCII. This precondition
--- is not checked. Resulting output will be corrupt if this condition
--- is not satisfied.
+{- | Encode a string in which all characters are ASCII. This precondition
+is not checked. Resulting output will be corrupt if this condition
+is not satisfied.
+-}
 encodeAsciiString :: ShortText -> Builder
 encodeAsciiString !str
   | n == 0 = B.word8 0x20
   | n <= 64 = B.copyCons (0x40 + fromIntegral (n - 1)) (Bytes.fromShortByteString (TS.toShortByteString str))
   | otherwise = B.word8 0xe0 <> B.shortTextUtf8 str <> B.word8 0xFC
-  where
+ where
   n = SBS.length (TS.toShortByteString str)
 
 -- | Encode a string.
@@ -249,35 +276,39 @@
 encodeKey :: ShortText -> Builder
 encodeKey !str = case SBS.length (TS.toShortByteString str) of
   0 -> B.word8 0x20
-  n | n <= 64
-    && TS.isAscii str
-    , w8 <- fromIntegral @Int @Word8 (n - 1)
-    -> B.copyCons (0x80 + w8) (Bytes.fromShortByteString (TS.toShortByteString str))
-  n | n < 56
-    , w8 <- fromIntegral @Int @Word8 (n - 2)
-    -> B.copyCons (0xC0 + w8) (Bytes.fromShortByteString (TS.toShortByteString str))
+  n
+    | n <= 64
+        && TS.isAscii str
+    , w8 <- fromIntegral @Int @Word8 (n - 1) ->
+        B.copyCons (0x80 + w8) (Bytes.fromShortByteString (TS.toShortByteString str))
+  n
+    | n < 56
+    , w8 <- fromIntegral @Int @Word8 (n - 2) ->
+        B.copyCons (0xC0 + w8) (Bytes.fromShortByteString (TS.toShortByteString str))
     | otherwise -> B.word8 0x34 <> B.shortTextUtf8 str <> B.word8 0xFC
 
--- | Encode a key in which all characters are ASCII. This precondition
--- is not checked. Resulting output will be corrupt if this condition
--- is not satisfied.
+{- | Encode a key in which all characters are ASCII. This precondition
+is not checked. Resulting output will be corrupt if this condition
+is not satisfied.
+-}
 encodeAsciiKey :: ShortText -> Builder
 encodeAsciiKey str = case SBS.length (TS.toShortByteString str) of
   0 -> B.word8 0x20
-  n | n <= 64
-    , w8 <- fromIntegral @Int @Word8 (n - 1)
-    -> B.word8 (0x80 + w8) <> B.shortTextUtf8 str
+  n
+    | n <= 64
+    , w8 <- fromIntegral @Int @Word8 (n - 1) ->
+        B.word8 (0x80 + w8) <> B.shortTextUtf8 str
     | otherwise -> B.word8 0x34 <> B.shortTextUtf8 str <> B.word8 0xFC
 
 vlqSmile :: Natural -> Builder
 vlqSmile n0 =
   let (rest, lastBits) = take6bits n0
    in loop rest <> B.word8 (lastBits .|. 0x80)
-  where
+ where
   loop n
     | n == 0 = mempty
-    | (rest, bits) <- take7bits n
-      = loop rest <> B.word8 bits
+    | (rest, bits) <- take7bits n =
+        loop rest <> B.word8 bits
   take7bits :: Natural -> (Natural, Word8)
   take7bits n = (n `unsafeShiftR` 7, fromIntegral @Natural @Word8 n .&. 0x7F)
   take6bits :: Natural -> (Natural, Word8)
@@ -305,13 +336,15 @@
 --
 -- Copied from bytebuild
 reverseBytes :: MutableByteArray s -> Int -> Int -> ST s ()
-{-# inline reverseBytes #-}
-reverseBytes arr begin end = go begin end where
-  go ixA ixB = if ixA < ixB
-    then do
-      a :: Word8 <- readByteArray arr ixA
-      b :: Word8 <- readByteArray arr ixB
-      writeByteArray arr ixA b
-      writeByteArray arr ixB a
-      go (ixA + 1) (ixB - 1)
-    else pure ()
+{-# INLINE reverseBytes #-}
+reverseBytes arr begin end = go begin end
+ where
+  go ixA ixB =
+    if ixA < ixB
+      then do
+        a :: Word8 <- readByteArray arr ixA
+        b :: Word8 <- readByteArray arr ixB
+        writeByteArray arr ixA b
+        writeByteArray arr ixB a
+        go (ixA + 1) (ixB - 1)
+      else pure ()
