packages feed

argo 0.2021.10.19 → 0.2021.10.24

raw patch · 39 files changed

+1018/−771 lines, 39 filesdep +genvaliditydep +genvalidity-containersdep +genvalidity-textdep −arrayPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: genvalidity, genvalidity-containers, genvalidity-text, transformers

Dependencies removed: array

API changes (from Hackage documentation)

- Argo: data Pair k v
- Argo: pattern Pair :: Text -> Value -> Pair String Value
- Argo.Class.FromValue: instance (Argo.Class.FromValue.FromValue a, GHC.Show.Show a) => Argo.Class.FromValue.FromValue (GHC.Base.NonEmpty a)
- Argo.Class.FromValue: instance Argo.Class.FromValue.FromValue Argo.Type.Value.Value
- Argo.Class.FromValue: instance Argo.Class.FromValue.FromValue Data.Text.Internal.Lazy.Text
- Argo.Class.FromValue: instance Argo.Class.FromValue.FromValue a => Argo.Class.FromValue.FromValue (GHC.Arr.Array GHC.Types.Int a)
- Argo.Class.ToValue: instance Argo.Class.ToValue.ToValue Argo.Type.Value.Value
- Argo.Class.ToValue: instance Argo.Class.ToValue.ToValue Data.Text.Internal.Lazy.Text
- Argo.Class.ToValue: instance Argo.Class.ToValue.ToValue a => Argo.Class.ToValue.ToValue (GHC.Arr.Array GHC.Types.Int a)
- Argo.Decode: decodeWith :: (Value -> Result a) -> ByteString -> Result a
- Argo.Decoder: array :: Decoder a -> Decoder (Array Int a)
- Argo.Decoder: arrayWith :: Decoder a -> Int -> [(Int, a)] -> Decoder (Array Int a)
- Argo.Pattern: pattern Pair :: Text -> Value -> Pair String Value
- Argo.Type: type Array = Array Int Value
- Argo.Type: type Object = Array Int (Pair String Value)
- Argo.Type.Array: Array :: Array Int a -> Array a
- Argo.Type.Array: decode :: Decoder a -> Decoder (Array a)
- Argo.Type.Array: encode :: (a -> Builder) -> Array a -> Builder
- Argo.Type.Array: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Argo.Type.Array.Array a)
- Argo.Type.Array: instance GHC.Classes.Eq a => GHC.Classes.Eq (Argo.Type.Array.Array a)
- Argo.Type.Array: instance GHC.Show.Show a => GHC.Show.Show (Argo.Type.Array.Array a)
- Argo.Type.Array: instance Language.Haskell.TH.Syntax.Lift a => Language.Haskell.TH.Syntax.Lift (Argo.Type.Array.Array a)
- Argo.Type.Array: newtype Array a
- Argo.Type.Boolean: Boolean :: Bool -> Boolean
- Argo.Type.Boolean: decode :: Decoder Boolean
- Argo.Type.Boolean: decodeFalse :: Decoder Boolean
- Argo.Type.Boolean: decodeTrue :: Decoder Boolean
- Argo.Type.Boolean: encode :: Boolean -> Builder
- Argo.Type.Boolean: instance Control.DeepSeq.NFData Argo.Type.Boolean.Boolean
- Argo.Type.Boolean: instance GHC.Classes.Eq Argo.Type.Boolean.Boolean
- Argo.Type.Boolean: instance GHC.Show.Show Argo.Type.Boolean.Boolean
- Argo.Type.Boolean: instance Language.Haskell.TH.Syntax.Lift Argo.Type.Boolean.Boolean
- Argo.Type.Boolean: newtype Boolean
- Argo.Type.Null: Null :: () -> Null
- Argo.Type.Null: decode :: Decoder Null
- Argo.Type.Null: encode :: Null -> Builder
- Argo.Type.Null: instance Control.DeepSeq.NFData Argo.Type.Null.Null
- Argo.Type.Null: instance GHC.Classes.Eq Argo.Type.Null.Null
- Argo.Type.Null: instance GHC.Show.Show Argo.Type.Null.Null
- Argo.Type.Null: instance Language.Haskell.TH.Syntax.Lift Argo.Type.Null.Null
- Argo.Type.Null: newtype Null
- Argo.Type.Number: Number :: Integer -> Integer -> Number
- Argo.Type.Number: data Number
- Argo.Type.Number: decode :: Decoder Number
- Argo.Type.Number: encode :: Number -> Builder
- Argo.Type.Number: factor :: (Num a, Integral b) => b -> a -> b -> (a, b)
- Argo.Type.Number: fromDigits :: ByteString -> Integer
- Argo.Type.Number: fromRational :: Rational -> Maybe Number
- Argo.Type.Number: instance Control.DeepSeq.NFData Argo.Type.Number.Number
- Argo.Type.Number: instance GHC.Classes.Eq Argo.Type.Number.Number
- Argo.Type.Number: instance GHC.Show.Show Argo.Type.Number.Number
- Argo.Type.Number: instance Language.Haskell.TH.Syntax.Lift Argo.Type.Number.Number
- Argo.Type.Number: intToInteger :: Int -> Integer
- Argo.Type.Number: negateIf :: Bool -> Integer -> Integer
- Argo.Type.Number: normalize :: Number -> Number
- Argo.Type.Number: number :: Integer -> Integer -> Number
- Argo.Type.Number: toRational :: Number -> Rational
- Argo.Type.Number: word8ToInteger :: Word8 -> Integer
- Argo.Type.Object: Object :: Array Int (Pair String a) -> Object a
- Argo.Type.Object: decode :: Decoder a -> Decoder (Object a)
- Argo.Type.Object: encode :: (a -> Builder) -> Object a -> Builder
- Argo.Type.Object: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Argo.Type.Object.Object a)
- Argo.Type.Object: instance GHC.Classes.Eq a => GHC.Classes.Eq (Argo.Type.Object.Object a)
- Argo.Type.Object: instance GHC.Show.Show a => GHC.Show.Show (Argo.Type.Object.Object a)
- Argo.Type.Object: instance Language.Haskell.TH.Syntax.Lift a => Language.Haskell.TH.Syntax.Lift (Argo.Type.Object.Object a)
- Argo.Type.Object: newtype Object a
- Argo.Type.Pair: Pair :: (k, v) -> Pair k v
- Argo.Type.Pair: decode :: Decoder k -> Decoder v -> Decoder (Pair k v)
- Argo.Type.Pair: encode :: (k -> Builder) -> (v -> Builder) -> Pair k v -> Builder
- Argo.Type.Pair: instance (Control.DeepSeq.NFData k, Control.DeepSeq.NFData v) => Control.DeepSeq.NFData (Argo.Type.Pair.Pair k v)
- Argo.Type.Pair: instance (GHC.Classes.Eq k, GHC.Classes.Eq v) => GHC.Classes.Eq (Argo.Type.Pair.Pair k v)
- Argo.Type.Pair: instance (GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (Argo.Type.Pair.Pair k v)
- Argo.Type.Pair: instance (Language.Haskell.TH.Syntax.Lift k, Language.Haskell.TH.Syntax.Lift v) => Language.Haskell.TH.Syntax.Lift (Argo.Type.Pair.Pair k v)
- Argo.Type.Pair: newtype Pair k v
- Argo.Type.String: String :: Text -> String
- Argo.Type.String: combineSurrogatePair :: Char -> Char -> Char
- Argo.Type.String: combineSurrogatePairs :: String -> String
- Argo.Type.String: countConsecutive :: Word8 -> Int -> ByteString -> Int
- Argo.Type.String: decode :: Decoder String
- Argo.Type.String: encode :: String -> Builder
- Argo.Type.String: encodeChar :: BoundedPrim Word8
- Argo.Type.String: encodeLongEscape :: BoundedPrim Word8
- Argo.Type.String: encodeShortEscape :: Word8 -> BoundedPrim a
- Argo.Type.String: findAt :: Word8 -> Int -> ByteString -> Maybe Int
- Argo.Type.String: fromHexadecimalDigit :: Char -> Maybe Int
- Argo.Type.String: fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char
- Argo.Type.String: getClose :: ByteString -> Int -> Maybe Int
- Argo.Type.String: instance Control.DeepSeq.NFData Argo.Type.String.String
- Argo.Type.String: instance GHC.Classes.Eq Argo.Type.String.String
- Argo.Type.String: instance GHC.Show.Show Argo.Type.String.String
- Argo.Type.String: instance Language.Haskell.TH.Syntax.Lift Argo.Type.String.String
- Argo.Type.String: isHighSurrogate :: Char -> Bool
- Argo.Type.String: isLowSurrogate :: Char -> Bool
- Argo.Type.String: newtype String
- Argo.Type.String: unescapeString :: String -> Maybe String
- Argo.Type.String: unescapeText :: Text -> Maybe Text
- Argo.Type.String: word8ToWord16 :: Word8 -> Word16
- Argo.Type.Value: Array :: Array Value -> Value
- Argo.Type.Value: Boolean :: Boolean -> Value
- Argo.Type.Value: Null :: Null -> Value
- Argo.Type.Value: Number :: Number -> Value
- Argo.Type.Value: Object :: Object Value -> Value
- Argo.Type.Value: String :: String -> Value
- Argo.Type.Value: data Value
- Argo.Type.Value: decode :: Decoder Value
- Argo.Type.Value: encode :: Value -> Builder
- Argo.Type.Value: instance Control.DeepSeq.NFData Argo.Type.Value.Value
- Argo.Type.Value: instance GHC.Classes.Eq Argo.Type.Value.Value
- Argo.Type.Value: instance GHC.Show.Show Argo.Type.Value.Value
- Argo.Type.Value: instance Language.Haskell.TH.Syntax.Lift Argo.Type.Value.Value
+ Argo: Spaces :: Int -> Indent
+ Argo: Tab :: Indent
+ Argo: data Indent
+ Argo: data Name
+ Argo: encodeWith :: ToValue a => Indent -> a -> Builder
+ Argo: pattern Member :: Name -> Value -> Member
+ Argo: pattern Name :: Text -> Name
+ Argo: type Member = MemberOf Value
+ Argo.Class.FromValue: instance Argo.Class.FromValue.FromValue Argo.Json.Value.Value
+ Argo.Class.FromValue: instance Argo.Class.FromValue.FromValue Argo.Vendor.Text.LazyText
+ Argo.Class.FromValue: instance Argo.Class.FromValue.FromValue a => Argo.Class.FromValue.FromValue (GHC.Base.NonEmpty a)
+ Argo.Class.ToValue: instance Argo.Class.ToValue.ToValue Argo.Json.Value.Value
+ Argo.Class.ToValue: instance Argo.Class.ToValue.ToValue Argo.Vendor.Text.LazyText
+ Argo.Decoder: list :: Decoder a -> Decoder [a]
+ Argo.Decoder: listWith :: Decoder a -> [a] -> Decoder [a]
+ Argo.Encoder: Config :: Indent -> Int -> Config
+ Argo.Encoder: Spaces :: Int -> Indent
+ Argo.Encoder: Tab :: Indent
+ Argo.Encoder: [indent] :: Config -> Indent
+ Argo.Encoder: [level] :: Config -> Int
+ Argo.Encoder: data Config
+ Argo.Encoder: data Indent
+ Argo.Encoder: hasIndent :: Config -> Bool
+ Argo.Encoder: increaseLevel :: Config -> Config
+ Argo.Encoder: instance GHC.Classes.Eq Argo.Encoder.Config
+ Argo.Encoder: instance GHC.Classes.Eq Argo.Encoder.Indent
+ Argo.Encoder: instance GHC.Show.Show Argo.Encoder.Config
+ Argo.Encoder: instance GHC.Show.Show Argo.Encoder.Indent
+ Argo.Encoder: list :: Encoder () -> Encoder () -> Encoder () -> (a -> Encoder ()) -> [a] -> Encoder ()
+ Argo.Encoder: makeIndent :: Config -> Builder
+ Argo.Encoder: type Encoder = ReaderT Config (WriterT Builder Identity)
+ Argo.Json.Array: Array :: [value] -> ArrayOf value
+ Argo.Json.Array: decode :: Decoder value -> Decoder (ArrayOf value)
+ Argo.Json.Array: encode :: (value -> Encoder ()) -> ArrayOf value -> Encoder ()
+ Argo.Json.Array: instance Control.DeepSeq.NFData value => Control.DeepSeq.NFData (Argo.Json.Array.ArrayOf value)
+ Argo.Json.Array: instance GHC.Classes.Eq value => GHC.Classes.Eq (Argo.Json.Array.ArrayOf value)
+ Argo.Json.Array: instance GHC.Generics.Generic (Argo.Json.Array.ArrayOf value)
+ Argo.Json.Array: instance GHC.Show.Show value => GHC.Show.Show (Argo.Json.Array.ArrayOf value)
+ Argo.Json.Array: instance Language.Haskell.TH.Syntax.Lift value => Language.Haskell.TH.Syntax.Lift (Argo.Json.Array.ArrayOf value)
+ Argo.Json.Array: newtype ArrayOf value
+ Argo.Json.Boolean: Boolean :: Bool -> Boolean
+ Argo.Json.Boolean: decode :: Decoder Boolean
+ Argo.Json.Boolean: decodeFalse :: Decoder Boolean
+ Argo.Json.Boolean: decodeTrue :: Decoder Boolean
+ Argo.Json.Boolean: encode :: Boolean -> Encoder ()
+ Argo.Json.Boolean: instance Control.DeepSeq.NFData Argo.Json.Boolean.Boolean
+ Argo.Json.Boolean: instance GHC.Classes.Eq Argo.Json.Boolean.Boolean
+ Argo.Json.Boolean: instance GHC.Generics.Generic Argo.Json.Boolean.Boolean
+ Argo.Json.Boolean: instance GHC.Show.Show Argo.Json.Boolean.Boolean
+ Argo.Json.Boolean: instance Language.Haskell.TH.Syntax.Lift Argo.Json.Boolean.Boolean
+ Argo.Json.Boolean: newtype Boolean
+ Argo.Json.Member: Member :: Name -> value -> MemberOf value
+ Argo.Json.Member: data MemberOf value
+ Argo.Json.Member: decode :: Decoder value -> Decoder (MemberOf value)
+ Argo.Json.Member: encode :: (value -> Encoder ()) -> MemberOf value -> Encoder ()
+ Argo.Json.Member: instance Control.DeepSeq.NFData value => Control.DeepSeq.NFData (Argo.Json.Member.MemberOf value)
+ Argo.Json.Member: instance GHC.Classes.Eq value => GHC.Classes.Eq (Argo.Json.Member.MemberOf value)
+ Argo.Json.Member: instance GHC.Generics.Generic (Argo.Json.Member.MemberOf value)
+ Argo.Json.Member: instance GHC.Show.Show value => GHC.Show.Show (Argo.Json.Member.MemberOf value)
+ Argo.Json.Member: instance Language.Haskell.TH.Syntax.Lift value => Language.Haskell.TH.Syntax.Lift (Argo.Json.Member.MemberOf value)
+ Argo.Json.Name: Name :: String -> Name
+ Argo.Json.Name: decode :: Decoder Name
+ Argo.Json.Name: encode :: Name -> Encoder ()
+ Argo.Json.Name: instance Control.DeepSeq.NFData Argo.Json.Name.Name
+ Argo.Json.Name: instance GHC.Classes.Eq Argo.Json.Name.Name
+ Argo.Json.Name: instance GHC.Generics.Generic Argo.Json.Name.Name
+ Argo.Json.Name: instance GHC.Show.Show Argo.Json.Name.Name
+ Argo.Json.Name: instance Language.Haskell.TH.Syntax.Lift Argo.Json.Name.Name
+ Argo.Json.Name: newtype Name
+ Argo.Json.Null: Null :: () -> Null
+ Argo.Json.Null: decode :: Decoder Null
+ Argo.Json.Null: encode :: Null -> Encoder ()
+ Argo.Json.Null: instance Control.DeepSeq.NFData Argo.Json.Null.Null
+ Argo.Json.Null: instance GHC.Classes.Eq Argo.Json.Null.Null
+ Argo.Json.Null: instance GHC.Generics.Generic Argo.Json.Null.Null
+ Argo.Json.Null: instance GHC.Show.Show Argo.Json.Null.Null
+ Argo.Json.Null: instance Language.Haskell.TH.Syntax.Lift Argo.Json.Null.Null
+ Argo.Json.Null: newtype Null
+ Argo.Json.Number: Number :: Integer -> Integer -> Number
+ Argo.Json.Number: data Number
+ Argo.Json.Number: decode :: Decoder Number
+ Argo.Json.Number: encode :: Number -> Encoder ()
+ Argo.Json.Number: factor :: (Num a, Integral b) => b -> a -> b -> (a, b)
+ Argo.Json.Number: fromDigits :: ByteString -> Integer
+ Argo.Json.Number: fromRational :: Rational -> Maybe Number
+ Argo.Json.Number: instance Control.DeepSeq.NFData Argo.Json.Number.Number
+ Argo.Json.Number: instance GHC.Classes.Eq Argo.Json.Number.Number
+ Argo.Json.Number: instance GHC.Generics.Generic Argo.Json.Number.Number
+ Argo.Json.Number: instance GHC.Show.Show Argo.Json.Number.Number
+ Argo.Json.Number: instance Language.Haskell.TH.Syntax.Lift Argo.Json.Number.Number
+ Argo.Json.Number: intToInteger :: Int -> Integer
+ Argo.Json.Number: negateIf :: Bool -> Integer -> Integer
+ Argo.Json.Number: normalize :: Number -> Number
+ Argo.Json.Number: number :: Integer -> Integer -> Number
+ Argo.Json.Number: toRational :: Number -> Rational
+ Argo.Json.Number: word8ToInteger :: Word8 -> Integer
+ Argo.Json.Object: Object :: [MemberOf value] -> ObjectOf value
+ Argo.Json.Object: decode :: Decoder value -> Decoder (ObjectOf value)
+ Argo.Json.Object: encode :: (value -> Encoder ()) -> ObjectOf value -> Encoder ()
+ Argo.Json.Object: encodeElement :: (value -> Encoder ()) -> Int -> MemberOf value -> Encoder ()
+ Argo.Json.Object: instance Control.DeepSeq.NFData value => Control.DeepSeq.NFData (Argo.Json.Object.ObjectOf value)
+ Argo.Json.Object: instance GHC.Classes.Eq value => GHC.Classes.Eq (Argo.Json.Object.ObjectOf value)
+ Argo.Json.Object: instance GHC.Generics.Generic (Argo.Json.Object.ObjectOf value)
+ Argo.Json.Object: instance GHC.Show.Show value => GHC.Show.Show (Argo.Json.Object.ObjectOf value)
+ Argo.Json.Object: instance Language.Haskell.TH.Syntax.Lift value => Language.Haskell.TH.Syntax.Lift (Argo.Json.Object.ObjectOf value)
+ Argo.Json.Object: newtype ObjectOf value
+ Argo.Json.String: String :: Text -> String
+ Argo.Json.String: combineSurrogatePair :: Char -> Char -> Char
+ Argo.Json.String: combineSurrogatePairs :: String -> String
+ Argo.Json.String: countConsecutive :: Word8 -> Int -> ByteString -> Int
+ Argo.Json.String: decode :: Decoder String
+ Argo.Json.String: encode :: String -> Encoder ()
+ Argo.Json.String: encodeChar :: BoundedPrim Word8
+ Argo.Json.String: encodeLongEscape :: BoundedPrim Word8
+ Argo.Json.String: encodeShortEscape :: Word8 -> BoundedPrim a
+ Argo.Json.String: findAt :: Word8 -> Int -> ByteString -> Maybe Int
+ Argo.Json.String: fromHexadecimalDigit :: Char -> Maybe Int
+ Argo.Json.String: fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char
+ Argo.Json.String: getClose :: ByteString -> Int -> Maybe Int
+ Argo.Json.String: instance Control.DeepSeq.NFData Argo.Json.String.String
+ Argo.Json.String: instance GHC.Classes.Eq Argo.Json.String.String
+ Argo.Json.String: instance GHC.Generics.Generic Argo.Json.String.String
+ Argo.Json.String: instance GHC.Show.Show Argo.Json.String.String
+ Argo.Json.String: instance Language.Haskell.TH.Syntax.Lift Argo.Json.String.String
+ Argo.Json.String: isHighSurrogate :: Char -> Bool
+ Argo.Json.String: isLowSurrogate :: Char -> Bool
+ Argo.Json.String: newtype String
+ Argo.Json.String: unescapeString :: String -> Maybe String
+ Argo.Json.String: unescapeText :: Text -> Maybe Text
+ Argo.Json.String: word8ToWord16 :: Word8 -> Word16
+ Argo.Json.Value: Array :: ArrayOf Value -> Value
+ Argo.Json.Value: Boolean :: Boolean -> Value
+ Argo.Json.Value: Null :: Null -> Value
+ Argo.Json.Value: Number :: Number -> Value
+ Argo.Json.Value: Object :: ObjectOf Value -> Value
+ Argo.Json.Value: String :: String -> Value
+ Argo.Json.Value: data Value
+ Argo.Json.Value: decode :: Decoder Value
+ Argo.Json.Value: encode :: Value -> Encoder ()
+ Argo.Json.Value: instance Control.DeepSeq.NFData Argo.Json.Value.Value
+ Argo.Json.Value: instance GHC.Classes.Eq Argo.Json.Value.Value
+ Argo.Json.Value: instance GHC.Generics.Generic Argo.Json.Value.Value
+ Argo.Json.Value: instance GHC.Show.Show Argo.Json.Value.Value
+ Argo.Json.Value: instance Language.Haskell.TH.Syntax.Lift Argo.Json.Value.Value
+ Argo.Main: Config :: Bool -> Indent -> Bool -> Config
+ Argo.Main: FlagHelp :: Flag
+ Argo.Main: FlagSpaces :: String -> Flag
+ Argo.Main: FlagTab :: Flag
+ Argo.Main: FlagVersion :: Flag
+ Argo.Main: [configHelp] :: Config -> Bool
+ Argo.Main: [configIndent] :: Config -> Indent
+ Argo.Main: [configVersion] :: Config -> Bool
+ Argo.Main: applyFlag :: Config -> Flag -> Either String Config
+ Argo.Main: data Config
+ Argo.Main: data Flag
+ Argo.Main: defaultConfig :: Config
+ Argo.Main: instance GHC.Classes.Eq Argo.Main.Config
+ Argo.Main: instance GHC.Classes.Eq Argo.Main.Flag
+ Argo.Main: instance GHC.Show.Show Argo.Main.Config
+ Argo.Main: instance GHC.Show.Show Argo.Main.Flag
+ Argo.Main: main :: IO ()
+ Argo.Main: options :: [OptDescr Flag]
+ Argo.Main: quote :: String -> String
+ Argo.Main: version :: String
+ Argo.Pattern: pattern Member :: Name -> Value -> Member
+ Argo.Pattern: pattern Name :: Text -> Name
+ Argo.Pattern: type Array = [Value]
+ Argo.Pattern: type Member = MemberOf Value
+ Argo.Pattern: type Object = [Member]
- Argo: type Array = Array Int Value
+ Argo: type Array = [Value]
- Argo: type Object = Array Int (Pair String Value)
+ Argo: type Object = [Member]
- Argo.Class.FromValue: withArray :: String -> (Array Int Value -> Result a) -> Value -> Result a
+ Argo.Class.FromValue: withArray :: String -> (Array -> Result a) -> Value -> Result a
- Argo.Class.FromValue: withObject :: String -> (Array Int (Pair String Value) -> Result a) -> Value -> Result a
+ Argo.Class.FromValue: withObject :: String -> (Object -> Result a) -> Value -> Result a
- Argo.Encode: encodeWith :: (a -> Value) -> a -> Builder
+ Argo.Encode: encodeWith :: ToValue a => Indent -> a -> Builder

Files

argo.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2  name: argo-version: 0.2021.10.19+version: 0.2021.10.24  build-type: Simple category: JSON@@ -23,13 +23,13 @@  common library     build-depends:-        , array >= 0.5.4 && < 0.6         , base >= 4.14.0 && < 4.16         , bytestring >= 0.10.12 && < 0.11         , containers >= 0.6.4 && < 0.7         , deepseq >= 1.4.4 && < 1.5         , template-haskell >= 2.16.0 && < 2.18         , text >= 1.2.4 && < 1.3+        , transformers >= 0.5.6 && < 0.6     default-language: Haskell2010     ghc-options:         -Weverything@@ -58,6 +58,7 @@ library     import: library +    autogen-modules: Paths_argo     exposed-modules:         Argo         Argo.Class.FromValue@@ -65,20 +66,30 @@         Argo.Decode         Argo.Decoder         Argo.Encode+        Argo.Encoder+        Argo.Json.Array+        Argo.Json.Boolean+        Argo.Json.Member+        Argo.Json.Name+        Argo.Json.Null+        Argo.Json.Number+        Argo.Json.Object+        Argo.Json.String+        Argo.Json.Value         Argo.Literal+        Argo.Main         Argo.Pattern         Argo.QuasiQuoter         Argo.Result-        Argo.Type-        Argo.Type.Array-        Argo.Type.Boolean-        Argo.Type.Null-        Argo.Type.Number-        Argo.Type.Object-        Argo.Type.Pair-        Argo.Type.String-        Argo.Type.Value     hs-source-dirs: source/library+    other-modules:+        Argo.Vendor.ByteString+        Argo.Vendor.Builder+        Argo.Vendor.DeepSeq+        Argo.Vendor.TemplateHaskell+        Argo.Vendor.Text+        Argo.Vendor.Transformers+        Paths_argo  executable argo     import: executable@@ -90,6 +101,9 @@     import: executable      build-depends:+        , genvalidity >= 0.11.0 && < 0.12+        , genvalidity-containers >= 0.9.0 && < 0.10+        , genvalidity-text >= 0.7.0 && < 0.8         , tasty >= 1.4.2 && < 1.5         , tasty-hunit >= 0.10.0 && < 0.11         , tasty-quickcheck >= 0.10.1 && < 0.11
source/benchmark/Main.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE OverloadedStrings #-}  import qualified Argo-import qualified Data.Array import qualified Data.ByteString as ByteString import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Lazy as LazyByteString@@ -29,20 +28,20 @@             , Tasty.bench "10000 characters" . Tasty.nf encode . Argo.String . Text.pack $ replicate 10000 'a'             ]         , Tasty.bgroup "Array"-            [ Tasty.bench "empty" . Tasty.nf encode . Argo.Array $ array []-            , Tasty.bench "1 element" . Tasty.nf encode . Argo.Array . array $ replicate 1 Argo.Null-            , Tasty.bench "10 elements" . Tasty.nf encode . Argo.Array . array $ replicate 10 Argo.Null-            , Tasty.bench "100 elements" . Tasty.nf encode . Argo.Array . array $ replicate 100 Argo.Null-            , Tasty.bench "1000 elements" . Tasty.nf encode . Argo.Array . array $ replicate 1000 Argo.Null-            , Tasty.bench "10000 elements" . Tasty.nf encode . Argo.Array . array $ replicate 10000 Argo.Null+            [ Tasty.bench "empty" . Tasty.nf encode $ Argo.Array []+            , Tasty.bench "1 element" . Tasty.nf encode . Argo.Array $ replicate 1 Argo.Null+            , Tasty.bench "10 elements" . Tasty.nf encode . Argo.Array $ replicate 10 Argo.Null+            , Tasty.bench "100 elements" . Tasty.nf encode . Argo.Array $ replicate 100 Argo.Null+            , Tasty.bench "1000 elements" . Tasty.nf encode . Argo.Array $ replicate 1000 Argo.Null+            , Tasty.bench "10000 elements" . Tasty.nf encode . Argo.Array $ replicate 10000 Argo.Null             ]         , Tasty.bgroup "Object"-            [ Tasty.bench "empty" . Tasty.nf encode . Argo.Object $ array []-            , Tasty.bench "1 element" . Tasty.nf encode . Argo.Object . array . replicate 1 $ Argo.Pair "" Argo.Null-            , Tasty.bench "10 elements" . Tasty.nf encode . Argo.Object . array . replicate 10 $ Argo.Pair "" Argo.Null-            , Tasty.bench "100 elements" . Tasty.nf encode . Argo.Object . array . replicate 100 $ Argo.Pair "" Argo.Null-            , Tasty.bench "1000 elements" . Tasty.nf encode . Argo.Object . array . replicate 1000 $ Argo.Pair "" Argo.Null-            , Tasty.bench "10000 elements" . Tasty.nf encode . Argo.Object . array . replicate 10000 $ Argo.Pair "" Argo.Null+            [ Tasty.bench "empty" . Tasty.nf encode $ Argo.Object []+            , Tasty.bench "1 element" . Tasty.nf encode . Argo.Object . replicate 1 $ Argo.Member (Argo.Name "") Argo.Null+            , Tasty.bench "10 elements" . Tasty.nf encode . Argo.Object . replicate 10 $ Argo.Member (Argo.Name "") Argo.Null+            , Tasty.bench "100 elements" . Tasty.nf encode . Argo.Object . replicate 100 $ Argo.Member (Argo.Name "") Argo.Null+            , Tasty.bench "1000 elements" . Tasty.nf encode . Argo.Object . replicate 1000 $ Argo.Member (Argo.Name "") Argo.Null+            , Tasty.bench "10000 elements" . Tasty.nf encode . Argo.Object . replicate 10000 $ Argo.Member (Argo.Name "") Argo.Null             ]         ]     , Tasty.bgroup "decode" $ let decode = resultToMaybe . Argo.decode :: ByteString.ByteString -> Maybe Argo.Value in@@ -64,18 +63,30 @@             , Tasty.bench "short escape" $ Tasty.nf decode "\"\\n\""             , Tasty.bench "long escape" $ Tasty.nf decode "\"\\u001f\""             , Tasty.bench "surrogate pair" $ Tasty.nf decode "\"\\ud834\\udd1e\""+            , Tasty.bench "1 character" . Tasty.nf decode $ "\"" <> ByteString.replicate 1 0x61 <> "\""+            , Tasty.bench "10 characters" . Tasty.nf decode $ "\"" <> ByteString.replicate 10 0x61 <> "\""+            , Tasty.bench "100 characters" . Tasty.nf decode $ "\"" <> ByteString.replicate 100 0x61 <> "\""+            , Tasty.bench "1000 characters" . Tasty.nf decode $ "\"" <> ByteString.replicate 1000 0x61 <> "\""+            , Tasty.bench "10000 characters" . Tasty.nf decode $ "\"" <> ByteString.replicate 10000 0x61 <> "\""             ]         , Tasty.bgroup "Array"             [ Tasty.bench "empty" $ Tasty.nf decode "[]"+            , Tasty.bench "1 element" $ Tasty.nf decode "[null]"+            , Tasty.bench "10 elements" . Tasty.nf decode $ "[null" <> ByteString.pack (take (5 * 9) $ cycle [0x2c, 0x6e, 0x75, 0x6c, 0x6c]) <> "]"+            , Tasty.bench "100 elements" . Tasty.nf decode $ "[null" <> ByteString.pack (take (5 * 99) $ cycle [0x2c, 0x6e, 0x75, 0x6c, 0x6c]) <> "]"+            , Tasty.bench "1000 elements" . Tasty.nf decode $ "[null" <> ByteString.pack (take (5 * 999) $ cycle [0x2c, 0x6e, 0x75, 0x6c, 0x6c]) <> "]"+            , Tasty.bench "10000 elements" . Tasty.nf decode $ "[null" <> ByteString.pack (take (5 * 9999) $ cycle [0x2c, 0x6e, 0x75, 0x6c, 0x6c]) <> "]"             ]         , Tasty.bgroup "Object"             [ Tasty.bench "empty" $ Tasty.nf decode "{}"+            , Tasty.bench "1 element" $ Tasty.nf decode "{\"\":null}"+            , Tasty.bench "10 elements" . Tasty.nf decode $ "{\"\":null" <> ByteString.pack (take (5 * 9) $ cycle [0x2c, 0x22, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c]) <> "}"+            , Tasty.bench "100 elements" . Tasty.nf decode $ "{\"\":null" <> ByteString.pack (take (5 * 99) $ cycle [0x2c, 0x22, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c]) <> "}"+            , Tasty.bench "1000 elements" . Tasty.nf decode $ "{\"\":null" <> ByteString.pack (take (5 * 999) $ cycle [0x2c, 0x22, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c]) <> "}"+            , Tasty.bench "10000 elements" . Tasty.nf decode $ "{\"\":null" <> ByteString.pack (take (5 * 9999) $ cycle [0x2c, 0x22, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c]) <> "}"             ]         ]     ]--array :: [a] -> Data.Array.Array Int a-array xs = Data.Array.listArray (0, length xs - 1) xs  resultToMaybe :: Argo.Result a -> Maybe a resultToMaybe r = case r of
source/executable/Main.hs view
@@ -1,11 +1,4 @@-import qualified Argo-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Builder as Builder-import qualified System.IO as IO+import qualified Argo.Main as Argo  main :: IO ()-main = do-    contents <- ByteString.getContents-    case Argo.decode contents of-        Argo.Failure e -> fail e-        Argo.Success value -> Builder.hPutBuilder IO.stdout $ Argo.encode (value :: Argo.Value)+main = Argo.main
source/library/Argo.hs view
@@ -9,10 +9,15 @@         , Pattern.Array         , Pattern.Object         )-    , Type.Array-    , Pair.Pair(Pattern.Pair)-    , Type.Object+    , Pattern.Array+    , Name.Name+    , pattern Pattern.Name+    , Pattern.Member+    , pattern Pattern.Member+    , Pattern.Object     , Encode.encode+    , Encode.encodeWith+    , Encoder.Indent(Spaces, Tab)     , Decode.decode     , FromValue.FromValue(fromValue)     , ToValue.ToValue(toValue)@@ -24,9 +29,9 @@ import qualified Argo.Class.ToValue as ToValue import qualified Argo.Decode as Decode import qualified Argo.Encode as Encode+import qualified Argo.Encoder as Encoder+import qualified Argo.Json.Name as Name+import qualified Argo.Json.Value as Value import qualified Argo.Pattern as Pattern import qualified Argo.QuasiQuoter as QuasiQuoter import qualified Argo.Result as Result-import qualified Argo.Type as Type-import qualified Argo.Type.Pair as Pair-import qualified Argo.Type.Value as Value
source/library/Argo/Class/FromValue.hs view
@@ -2,21 +2,15 @@  module Argo.Class.FromValue where +import qualified Argo.Json.Number as Number+import qualified Argo.Json.Value as Value+import qualified Argo.Pattern as Pattern import qualified Argo.Result as Result-import qualified Argo.Type.Array as Array-import qualified Argo.Type.Boolean as Boolean-import qualified Argo.Type.Number as Number-import qualified Argo.Type.Object as Object-import qualified Argo.Type.Pair as Pair-import qualified Argo.Type.String as String-import qualified Argo.Type.Value as Value-import qualified Data.Array+import qualified Argo.Vendor.Text as Text import qualified Data.Bits as Bits import qualified Data.Int as Int import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map-import qualified Data.Text as Text-import qualified Data.Text.Lazy as LazyText import qualified Data.Word as Word  class FromValue a where@@ -66,7 +60,7 @@ instance FromValue Integer where     fromValue = withNumber "Integer" $ \ x y ->         if y < 0-        then fail $ "expected integer but got " <> show (Number.number x y)+        then fail $ "expected integer but got " <> show (Pattern.Number x y)         else pure $ x * 10 ^ y  instance FromValue Float where@@ -83,70 +77,62 @@ instance FromValue Text.Text where     fromValue = withString "Text" pure -instance FromValue LazyText.Text where-    fromValue = fmap LazyText.fromStrict . fromValue+instance FromValue Text.LazyText where+    fromValue = fmap Text.fromStrict . fromValue  instance FromValue a => FromValue (Maybe a) where     fromValue x = case x of-        Value.Null _ -> pure Nothing+        Pattern.Null -> pure Nothing         _ -> Just <$> fromValue x  instance FromValue () where-    fromValue x = do-        [] <- fromValue x :: Result.Result [Value.Value]-        pure ()+    fromValue = withArray "()" $ \ xs -> case xs of+        [] -> pure ()+        _ -> fail $ "expected empty list but got " <> show xs  instance (FromValue a, FromValue b) => FromValue (a, b) where-    fromValue x = do-        [y, z] <- fromValue x-        (,) <$> fromValue y <*> fromValue z--instance FromValue a => FromValue (Data.Array.Array Int a) where-    fromValue = withArray "Array" $ traverse fromValue+    fromValue = withArray "(a, b)" $ \ xs -> case xs of+        [x, y] -> (,) <$> fromValue x <*> fromValue y+        _ -> fail $ "expected tuple but got " <> show xs  instance FromValue a => FromValue [a] where-    fromValue =-        let-            arrayToList :: Data.Array.Array Int b -> [b]-            arrayToList = Data.Array.elems-        in fmap arrayToList . fromValue+    fromValue = withArray "[a]" $ traverse fromValue -instance (FromValue a, Show a) => FromValue (NonEmpty.NonEmpty a) where+instance FromValue a => FromValue (NonEmpty.NonEmpty a) where     fromValue value = do         list <- fromValue value         case NonEmpty.nonEmpty list of-            Nothing -> fail $ "expected non-empty list but got " <> show list+            Nothing -> fail "unexpected empty list"             Just nonEmpty -> pure nonEmpty  instance FromValue a => FromValue (Map.Map Text.Text a) where     fromValue = withObject "Map"         $ fmap Map.fromList-        . traverse (\ (Pair.Pair (String.String k, v)) -> (,) k <$> fromValue v)-        . Data.Array.elems+        . traverse (\ (Pattern.Member (Pattern.Name k) v) -> (,) k <$> fromValue v)  withBoolean :: String -> (Bool -> Result.Result a) -> Value.Value -> Result.Result a withBoolean s f x = case x of-    Value.Boolean (Boolean.Boolean y) -> f y+    Pattern.Boolean y -> f y     _ -> fail $ "expected " <> s <> " but got " <> show x  withNumber :: String -> (Integer -> Integer -> Result.Result a) -> Value.Value -> Result.Result a withNumber s f x = case x of-    Value.Number (Number.Number y z) -> f y z+    Pattern.Number y z -> f y z     _ -> fail $ "expected " <> s <> " but got " <> show x  withString :: String -> (Text.Text -> Result.Result a) -> Value.Value -> Result.Result a withString s f x = case x of-    Value.String (String.String y) -> f y+    Pattern.String y -> f y     _ -> fail $ "expected " <> s <> " but got " <> show x -withArray :: String -> (Data.Array.Array Int Value.Value -> Result.Result a) -> Value.Value -> Result.Result a+withArray :: String -> (Pattern.Array -> Result.Result a) -> Value.Value -> Result.Result a withArray s f x = case x of-    Value.Array (Array.Array y) -> f y+    Pattern.Array y -> f y     _ -> fail $ "expected " <> s <> " but got " <> show x -withObject :: String -> (Data.Array.Array Int (Pair.Pair String.String Value.Value) -> Result.Result a) -> Value.Value -> Result.Result a+withObject :: String -> (Pattern.Object -> Result.Result a) -> Value.Value -> Result.Result a withObject s f x = case x of-    Value.Object (Object.Object y) -> f y+    Pattern.Object y -> f y     _ -> fail $ "expected " <> s <> " but got " <> show x  viaInteger :: (Integral a, Bits.Bits a) => Value.Value -> Result.Result a
source/library/Argo/Class/ToValue.hs view
@@ -2,21 +2,14 @@  module Argo.Class.ToValue where -import qualified Argo.Type.Array as Array-import qualified Argo.Type.Boolean as Boolean-import qualified Argo.Type.Null as Null-import qualified Argo.Type.Number as Number-import qualified Argo.Type.Object as Object-import qualified Argo.Type.Pair as Pair-import qualified Argo.Type.String as String-import qualified Argo.Type.Value as Value-import qualified Data.Array+import qualified Argo.Json.Number as Number+import qualified Argo.Json.Value as Value+import qualified Argo.Pattern as Pattern+import qualified Argo.Vendor.Text as Text import qualified Data.Int as Int import qualified Data.List as List import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map-import qualified Data.Text as Text-import qualified Data.Text.Lazy as LazyText import qualified Data.Word as Word import qualified Numeric @@ -27,7 +20,7 @@     toValue = id  instance ToValue Bool where-    toValue = Value.Boolean . Boolean.Boolean+    toValue = Pattern.Boolean  instance ToValue Char where     toValue = toValue . Text.singleton@@ -63,7 +56,7 @@     toValue = toValue . toInteger  instance ToValue Integer where-    toValue = Value.Number . flip Number.number 0+    toValue = flip Pattern.Number 0  instance ToValue Float where     toValue = realFloatToValue@@ -75,13 +68,13 @@     toValue = toValue . Text.pack  instance ToValue Text.Text where-    toValue = Value.String . String.String+    toValue = Pattern.String -instance ToValue LazyText.Text where-    toValue = toValue . LazyText.toStrict+instance ToValue Text.LazyText where+    toValue = toValue . Text.toStrict  instance ToValue a => ToValue (Maybe a) where-    toValue = maybe (Value.Null $ Null.Null ()) toValue+    toValue = maybe Pattern.Null toValue  instance ToValue () where     toValue = const $ toValue ([] :: [Value.Value])@@ -89,30 +82,21 @@ instance (ToValue a, ToValue b) => ToValue (a, b) where     toValue (x, y) = toValue [toValue x, toValue y] -instance ToValue a => ToValue (Data.Array.Array Int a) where-    toValue = Value.Array . Array.Array . fmap toValue- instance ToValue a => ToValue [a] where-    toValue =-        let-            listToArray :: [b] -> Data.Array.Array Int b-            listToArray xs = Data.Array.listArray (0, length xs - 1) xs-        in toValue . listToArray+    toValue = Pattern.Array . fmap toValue  instance ToValue a => ToValue (NonEmpty.NonEmpty a) where     toValue = toValue . NonEmpty.toList  instance ToValue a => ToValue (Map.Map Text.Text a) where-    toValue x = Value.Object-        . Object.Object-        . Data.Array.listArray (0, Map.size x - 1)-        . fmap (\ (k, v) -> Pair.Pair (String.String k, toValue v))+    toValue x = Pattern.Object+        . fmap (\ (k, v) -> Pattern.Member (Pattern.Name k) (toValue v))         $ Map.toAscList x  realFloatToValue :: RealFloat a => a -> Value.Value realFloatToValue x-    | isNaN x = Value.Null $ Null.Null ()-    | isInfinite x = Value.Null $ Null.Null ()+    | isNaN x = Pattern.Null+    | isInfinite x = Pattern.Null     | otherwise =         let isNegative = x < 0         in Value.Number
source/library/Argo/Decode.hs view
@@ -2,15 +2,12 @@  import qualified Argo.Class.FromValue as FromValue import qualified Argo.Decoder as Decoder+import qualified Argo.Json.Value as Value import qualified Argo.Result as Result-import qualified Argo.Type.Value as Value-import qualified Data.ByteString as ByteString+import qualified Argo.Vendor.ByteString as ByteString  decode :: FromValue.FromValue a => ByteString.ByteString -> Result.Result a-decode = decodeWith FromValue.fromValue--decodeWith :: (Value.Value -> Result.Result a) -> ByteString.ByteString -> Result.Result a-decodeWith f x =+decode x =     case Decoder.run (Decoder.spaces *> Value.decode <* Decoder.eof) x of         Result.Failure e -> Result.Failure e-        Result.Success (_, y) -> f y+        Result.Success (_, y) -> FromValue.fromValue y
source/library/Argo/Decoder.hs view
@@ -2,10 +2,9 @@  import qualified Argo.Literal as Literal import qualified Argo.Result as Result+import qualified Argo.Vendor.ByteString as ByteString import qualified Control.Applicative as Applicative import qualified Control.Monad as Monad-import qualified Data.Array as Array-import qualified Data.ByteString as ByteString import qualified Data.Word as Word  newtype Decoder a = Decoder@@ -39,19 +38,19 @@         Result.Failure _ -> run dy b1         Result.Success (b2, x) -> Result.Success (b2, x) -array :: Decoder a -> Decoder (Array.Array Int a)-array f = arrayWith f 0 []+list :: Decoder a -> Decoder [a]+list f = listWith f [] -arrayWith :: Decoder a -> Int -> [(Int, a)] -> Decoder (Array.Array Int a)-arrayWith f n xs = do+listWith :: Decoder a -> [a] -> Decoder [a]+listWith f xs = do     m <- Applicative.optional $ do-        Monad.when (n /= 0) $ do+        Monad.unless (null xs) $ do             word8 Literal.comma             spaces         f     case m of-        Nothing -> pure $ Array.array (0, n - 1) xs-        Just x -> arrayWith f (n + 1) $ (n, x) : xs+        Nothing -> pure $ reverse xs+        Just x -> listWith f $ x : xs  byteString :: ByteString.ByteString -> Decoder () byteString x = do
source/library/Argo/Encode.hs view
@@ -1,11 +1,26 @@ module Argo.Encode where  import qualified Argo.Class.ToValue as ToValue-import qualified Argo.Type.Value as Value-import qualified Data.ByteString.Builder as Builder+import qualified Argo.Encoder as Encoder+import qualified Argo.Json.Value as Value+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.Transformers as Trans+import qualified Control.Monad as Monad+import qualified Data.Functor.Identity as Identity  encode :: ToValue.ToValue a => a -> Builder.Builder-encode = encodeWith ToValue.toValue+encode = encodeWith $ Encoder.Spaces 0 -encodeWith :: (a -> Value.Value) -> a -> Builder.Builder-encodeWith f = Value.encode . f+encodeWith :: ToValue.ToValue a => Encoder.Indent -> a -> Builder.Builder+encodeWith i x =+    let c = Encoder.Config { Encoder.indent = i, Encoder.level = 0 }+    in Identity.runIdentity+    . Trans.execWriterT+    . flip Trans.runReaderT c+    $ do+        Value.encode $ ToValue.toValue x+        Monad.when (Encoder.hasIndent c)+            . Trans.lift+            . Trans.tell+            $ Builder.word8 Literal.newLine
+ source/library/Argo/Encoder.hs view
@@ -0,0 +1,57 @@+module Argo.Encoder where++import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.Transformers as Trans+import qualified Control.Monad as Monad+import qualified Data.Functor.Identity as Identity+import qualified Data.Semigroup as Semigroup++type Encoder = Trans.ReaderT Config (Trans.WriterT Builder.Builder Identity.Identity)++data Config = Config+    { indent :: Indent+    , level :: Int+    } deriving (Eq, Show)++data Indent+    = Spaces Int+    | Tab+    deriving (Eq, Show)++hasIndent :: Config -> Bool+hasIndent x = case indent x of+    Spaces y -> y > 0+    Tab -> True++increaseLevel :: Config -> Config+increaseLevel x = x { level = level x + 1 }++list :: Encoder () -> Encoder () -> Encoder () -> (a -> Encoder ()) -> [a] -> Encoder ()+list l r s f xs = case xs of+    [] -> do+        l+        r+    x : ys -> do+        l+        c <- Trans.ask+        let newLine = if hasIndent c then Builder.word8 Literal.newLine else mempty+        Trans.local increaseLevel $ do+            i <- Trans.asks makeIndent+            Trans.lift . Trans.tell $ newLine <> i+            f x+            Monad.forM_ ys $ \ y -> do+                s+                Trans.lift . Trans.tell $ newLine <> i+                f y+        Trans.lift . Trans.tell $ newLine <> makeIndent c+        r++makeIndent :: Config -> Builder.Builder+makeIndent x = case indent x of+    Spaces y -> if y <= 0 then mempty else+        Semigroup.stimesMonoid (level x)+        . Semigroup.stimes y+        $ Builder.word8 Literal.space+    Tab -> Semigroup.stimesMonoid (level x)+        $ Builder.word8 Literal.horizontalTabulation
+ source/library/Argo/Json/Array.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Array where++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Transformers as Trans+import qualified GHC.Generics as Generics++newtype ArrayOf value+    = Array [value]+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: (value -> Encoder.Encoder ()) -> ArrayOf value -> Encoder.Encoder ()+encode f (Array xs) = Encoder.list+    (Trans.lift . Trans.tell $ Builder.word8 Literal.leftSquareBracket)+    (Trans.lift . Trans.tell $ Builder.word8 Literal.rightSquareBracket)+    (Trans.lift . Trans.tell $ Builder.word8 Literal.comma)+    f+    xs++decode :: Decoder.Decoder value -> Decoder.Decoder (ArrayOf value)+decode f = do+    Decoder.word8 Literal.leftSquareBracket+    Decoder.spaces+    xs <- Decoder.list f+    Decoder.word8 Literal.rightSquareBracket+    Decoder.spaces+    pure $ Array xs
+ source/library/Argo/Json/Boolean.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Boolean where++import Control.Applicative ((<|>))++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Transformers as Trans+import qualified GHC.Generics as Generics++newtype Boolean+    = Boolean Bool+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: Boolean -> Encoder.Encoder ()+encode (Boolean x) = Trans.lift+    . Trans.tell+    . Builder.byteString+    $ if x then Literal.true else Literal.false++decode :: Decoder.Decoder Boolean+decode = decodeFalse <|> decodeTrue++decodeFalse :: Decoder.Decoder Boolean+decodeFalse = Boolean False <$ Decoder.byteString Literal.false <* Decoder.spaces++decodeTrue :: Decoder.Decoder Boolean+decodeTrue = Boolean True <$ Decoder.byteString Literal.true <* Decoder.spaces
+ source/library/Argo/Json/Member.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Member where++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Json.Name as Name+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Transformers as Trans+import qualified Control.Monad as Monad+import qualified GHC.Generics as Generics++data MemberOf value+    = Member Name.Name value+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: (value -> Encoder.Encoder ()) -> MemberOf value -> Encoder.Encoder ()+encode f (Member x y) = do+    Name.encode x+    Trans.lift . Trans.tell $ Builder.word8 Literal.colon+    config <- Trans.ask+    Monad.when (Encoder.hasIndent config)+        . Trans.lift+        . Trans.tell+        $ Builder.word8 Literal.space+    f y++decode :: Decoder.Decoder value -> Decoder.Decoder (MemberOf value)+decode g = Member+    <$> Name.decode <* Decoder.word8 Literal.colon <* Decoder.spaces+    <*> g
+ source/library/Argo/Json/Name.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Name where++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Json.String as String+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified GHC.Generics as Generics++newtype Name+    = Name String.String+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: Name -> Encoder.Encoder ()+encode (Name x) = String.encode x++decode :: Decoder.Decoder Name+decode = Name <$> String.decode
+ source/library/Argo/Json/Null.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Null where++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Transformers as Trans+import qualified GHC.Generics as Generics++newtype Null+    = Null ()+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: Null -> Encoder.Encoder ()+encode = const . Trans.lift . Trans.tell $ Builder.byteString Literal.null++decode :: Decoder.Decoder Null+decode = Null () <$ Decoder.byteString Literal.null <* Decoder.spaces
+ source/library/Argo/Json/Number.hs view
@@ -0,0 +1,109 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Number where++import Data.Ratio ((%))++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.ByteString as ByteString+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Transformers as Trans+import qualified Control.Applicative as Applicative+import qualified Control.Monad as Monad+import qualified Data.Bool as Bool+import qualified Data.Maybe as Maybe+import qualified Data.Ratio as Ratio+import qualified Data.Word as Word+import qualified GHC.Generics as Generics++data Number+    = Number Integer Integer+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++number :: Integer -> Integer -> Number+number x = normalize . Number x++normalize :: Number -> Number+normalize (Number x y) =+    if x == 0+    then Number 0 0+    else let (q, r) = quotRem x 10 in if r == 0+    then normalize $ Number q (y + 1)+    else Number x y++encode :: Number -> Encoder.Encoder ()+encode (Number x y) = do+    Trans.lift . Trans.tell $ Builder.integerDec x+    Monad.when (y /= 0)+        . Trans.lift+        . Trans.tell+        $ Builder.word8 Literal.latinSmallLetterE+        <> Builder.integerDec y++decode :: Decoder.Decoder Number+decode = do+    ni <- fmap Maybe.isJust . Applicative.optional $ Decoder.word8 Literal.hyphenMinus+    i <- Decoder.takeWhile1 Decoder.isDigit+    Monad.when (ByteString.length i > 1 && ByteString.elemIndex Literal.digitZero i == Just 0)+        $ fail "leading zero"+    f <- fmap (Maybe.fromMaybe ByteString.empty) . Applicative.optional $ do+        Decoder.word8 Literal.fullStop+        Decoder.takeWhile1 Decoder.isDigit+    (ne, e) <- fmap (Maybe.fromMaybe (False, ByteString.empty)) . Applicative.optional $ do+        Monad.void+            . Decoder.satisfy+            $ \ x -> x == Literal.latinSmallLetterE || x == Literal.latinCapitalLetterE+        ne <- fmap (== Just Literal.hyphenMinus)+            . Applicative.optional+            . Decoder.satisfy+            $ \ x -> x == Literal.hyphenMinus || x == Literal.plusSign+        e <- Decoder.takeWhile1 Decoder.isDigit+        pure (ne, e)+    Decoder.spaces+    pure $ number+        (negateIf ni $ (fromDigits i * 10 ^ ByteString.length f) + fromDigits f)+        (negateIf ne (fromDigits e) - intToInteger (ByteString.length f))++negateIf :: Bool -> Integer -> Integer+negateIf = Bool.bool id negate++fromDigits :: ByteString.ByteString -> Integer+fromDigits = ByteString.foldl' (\ a e -> (a * 10) + word8ToInteger (e - 0x30)) 0++intToInteger :: Int -> Integer+intToInteger = fromIntegral++word8ToInteger :: Word.Word8 -> Integer+word8ToInteger = fromIntegral++toRational :: Number -> Rational+toRational (Number x y) =+    if y < 0+    then x % (10 ^ (-y))+    else fromInteger $ x * 10 ^ y++fromRational :: Rational -> Maybe Number+fromRational r =+    let+        n = Ratio.numerator r+        d1 = Ratio.denominator r+        (t, d2) = factor 2 (0 :: Integer) d1+        (f, d3) = factor 5 (0 :: Integer) d2+        p = max t f+    in if d3 == 1+    then Just $ number (n * 2 ^ (p - t) * 5 ^ (p - f)) (-p)+    else Nothing++-- factor d 0 x = (p, y) <=> x = (d ^ p) * y+factor :: (Num a, Integral b) => b -> a -> b -> (a, b)+factor d n x =+    let (q, r) = quotRem x d+    in if x /= 0 && r == 0+    then factor d (n + 1) q+    else (n, x)
+ source/library/Argo/Json/Object.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Object where++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Json.Member as Member+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Transformers as Trans+import qualified Control.Monad as Monad+import qualified GHC.Generics as Generics++newtype ObjectOf value+    = Object [Member.MemberOf value]+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: (value -> Encoder.Encoder ()) -> ObjectOf value -> Encoder.Encoder ()+encode f (Object xs) = Encoder.list+    (Trans.lift . Trans.tell $ Builder.word8 Literal.leftCurlyBracket)+    (Trans.lift . Trans.tell $ Builder.word8 Literal.rightCurlyBracket)+    (Trans.lift . Trans.tell $ Builder.word8 Literal.comma)+    (Member.encode f)+    xs++encodeElement :: (value -> Encoder.Encoder ()) -> Int -> Member.MemberOf value -> Encoder.Encoder ()+encodeElement f i x = do+    Monad.when (i > 0) . Trans.lift . Trans.tell $ Builder.word8 Literal.comma+    Member.encode f x++decode :: Decoder.Decoder value -> Decoder.Decoder (ObjectOf value)+decode f = do+    Decoder.word8 Literal.leftCurlyBracket+    Decoder.spaces+    xs <- Decoder.list $ Member.decode f+    Decoder.word8 Literal.rightCurlyBracket+    Decoder.spaces+    pure $ Object xs
+ source/library/Argo/Json/String.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.String where++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Literal as Literal+import qualified Argo.Vendor.Builder as Builder+import qualified Argo.Vendor.ByteString as ByteString+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Text as Text+import qualified Argo.Vendor.Transformers as Trans+import qualified Control.Monad as Monad+import qualified Data.Char as Char+import qualified Data.Word as Word+import qualified GHC.Generics as Generics++newtype String+    = String Text.Text+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: Argo.Json.String.String -> Encoder.Encoder ()+encode (String x) = Trans.lift+    . Trans.tell+    $ Builder.word8 Literal.quotationMark+    <> Text.encodeUtf8BuilderEscaped encodeChar x+    <> Builder.word8 Literal.quotationMark++encodeChar :: Builder.BoundedPrim Word.Word8+encodeChar =+    Builder.condB (== Literal.quotationMark) (encodeShortEscape Literal.quotationMark)+    . Builder.condB (== Literal.reverseSolidus) (encodeShortEscape Literal.reverseSolidus)+    . Builder.condB (== Literal.backspace) (encodeShortEscape Literal.latinSmallLetterB)+    . Builder.condB (== Literal.formFeed) (encodeShortEscape Literal.latinSmallLetterF)+    . Builder.condB (== Literal.newLine) (encodeShortEscape Literal.latinSmallLetterN)+    . Builder.condB (== Literal.carriageReturn) (encodeShortEscape Literal.latinSmallLetterR)+    . Builder.condB (== Literal.horizontalTabulation) (encodeShortEscape Literal.latinSmallLetterT)+    . Builder.condB (< Literal.space) encodeLongEscape+    $ Builder.liftFixedToBounded Builder.word8F++encodeShortEscape :: Word.Word8 -> Builder.BoundedPrim a+encodeShortEscape x = Builder.liftFixedToBounded+    $ const (Literal.reverseSolidus, x)+    Builder.>$< Builder.word8F+    Builder.>*< Builder.word8F++encodeLongEscape :: Builder.BoundedPrim Word.Word8+encodeLongEscape = Builder.liftFixedToBounded+    $ (\ x -> (Literal.reverseSolidus, (Literal.latinSmallLetterU, word8ToWord16 x)))+    Builder.>$< Builder.word8F+    Builder.>*< Builder.word8F+    Builder.>*< Builder.word16HexFixed++word8ToWord16 :: Word.Word8 -> Word.Word16+word8ToWord16 = fromIntegral++decode :: Decoder.Decoder Argo.Json.String.String+decode = do+    Decoder.word8 Literal.quotationMark+    b1 <- Decoder.get+    i <- case getClose b1 0 of+        Nothing -> fail "unterminated string"+        Just i -> pure i+    let (xs, b2) = ByteString.splitAt i b1+    Monad.when (ByteString.any (< Literal.space) xs) $ fail "unescaped control character"+    Decoder.put b2+    Decoder.word8 Literal.quotationMark+    Decoder.spaces+    case Text.decodeUtf8' xs of+        Left e -> fail $ show e+        Right x -> case unescapeText x of+            Nothing -> fail "invalid escape"+            Just y -> pure $ String y++findAt :: Word.Word8 -> Int -> ByteString.ByteString -> Maybe Int+findAt x i = fmap (+ i) . ByteString.elemIndex x . ByteString.drop i++countConsecutive :: Word.Word8 -> Int -> ByteString.ByteString -> Int+countConsecutive x i = ByteString.length . ByteString.takeWhileEnd (== x) . ByteString.take i++getClose :: ByteString.ByteString -> Int -> Maybe Int+getClose b i = do+    j <- findAt Literal.quotationMark i b+    let n = countConsecutive Literal.reverseSolidus j b+    if even n then Just j else getClose b $ j + 1++unescapeText :: Text.Text -> Maybe Text.Text+unescapeText = fmap (Text.pack . combineSurrogatePairs) . unescapeString . Text.unpack++combineSurrogatePairs :: Prelude.String -> Prelude.String+combineSurrogatePairs xs = case xs of+    "" -> xs+    x : y : zs | isHighSurrogate x && isLowSurrogate y ->+        combineSurrogatePair x y : combineSurrogatePairs zs+    x : ys -> x : combineSurrogatePairs ys++combineSurrogatePair :: Char -> Char -> Char+combineSurrogatePair hi lo = Char.chr+    $ 0x10000+    + ((Char.ord hi - 0xd800) * 0x400)+    + (Char.ord lo - 0xdc00)++isHighSurrogate :: Char -> Bool+isHighSurrogate x = '\xd800' <= x && x <= '\xdbff'++isLowSurrogate :: Char -> Bool+isLowSurrogate x = '\xdc00' <= x && x <= '\xdfff'++unescapeString :: Prelude.String -> Maybe Prelude.String+unescapeString xs = case xs of+    "" -> pure xs+    '\\' : ys -> case ys of+        "" -> fail "empty escape"+        x : zs -> case x of+            '"' -> ('"' :) <$> unescapeString zs+            '\\' -> ('\\' :) <$> unescapeString zs+            '/' -> ('/' :) <$> unescapeString zs+            'b' -> ('\b' :) <$> unescapeString zs+            'f' -> ('\f' :) <$> unescapeString zs+            'n' -> ('\n' :) <$> unescapeString zs+            'r' -> ('\r' :) <$> unescapeString zs+            't' -> ('\t' :) <$> unescapeString zs+            'u' -> case zs of+                a : b : c : d : es | Just y <- fromLongEscape a b c d ->+                    (y :) <$> unescapeString es+                _ -> fail "invalid long escape"+            _ -> fail "invalid short escape"+    x : ys -> (x :) <$> unescapeString ys++fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char+fromLongEscape a b c d = do+    w <- fromHexadecimalDigit a+    x <- fromHexadecimalDigit b+    y <- fromHexadecimalDigit c+    z <- fromHexadecimalDigit d+    pure . Char.chr $ (0x1000 * w) + (0x100 * x) + (0x10 * y) + z++fromHexadecimalDigit :: Char -> Maybe Int+fromHexadecimalDigit x =+    if Char.isHexDigit x then Just $ Char.digitToInt x else Nothing
+ source/library/Argo/Json/Value.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}++module Argo.Json.Value where++import Control.Applicative ((<|>))++import qualified Argo.Decoder as Decoder+import qualified Argo.Encoder as Encoder+import qualified Argo.Json.Array as Array+import qualified Argo.Json.Boolean as Boolean+import qualified Argo.Json.Null as Null+import qualified Argo.Json.Number as Number+import qualified Argo.Json.Object as Object+import qualified Argo.Json.String as String+import qualified Argo.Vendor.DeepSeq as DeepSeq+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified GHC.Generics as Generics++data Value+    = Null Null.Null+    | Boolean Boolean.Boolean+    | Number Number.Number+    | String String.String+    | Array (Array.ArrayOf Value)+    | Object (Object.ObjectOf Value)+    deriving (Eq, Generics.Generic, TH.Lift, DeepSeq.NFData, Show)++encode :: Value -> Encoder.Encoder ()+encode x = case x of+    Null y -> Null.encode y+    Boolean y -> Boolean.encode y+    Number y -> Number.encode y+    String y -> String.encode y+    Array y -> Array.encode encode y+    Object y -> Object.encode encode y++decode :: Decoder.Decoder Value+decode =+    Null <$> Null.decode+    <|> Boolean <$> Boolean.decode+    <|> Number <$> Number.decode+    <|> String <$> String.decode+    <|> Array <$> Array.decode decode+    <|> Object <$> Object.decode decode
source/library/Argo/Literal.hs view
@@ -1,6 +1,6 @@ module Argo.Literal where -import qualified Data.ByteString as ByteString+import qualified Argo.Vendor.ByteString as ByteString import qualified Data.Word as Word  backspace :: Word.Word8
+ source/library/Argo/Main.hs view
@@ -0,0 +1,81 @@+module Argo.Main where++import qualified Argo+import qualified Argo.Encoder as Encoder+import qualified Control.Monad as Monad+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as Builder+import qualified Data.Version as Version+import qualified Paths_argo as This+import qualified System.Console.GetOpt as Console+import qualified System.Environment as Environment+import qualified System.Exit as Exit+import qualified System.IO as IO+import qualified Text.Read as Read++main :: IO ()+main = do+    name <- Environment.getProgName+    arguments <- Environment.getArgs+    let (flags, as, os, es) = Console.getOpt' Console.Permute options arguments+    mapM_ (IO.hPutStrLn IO.stderr . mappend "unknown argument " . quote) as+    mapM_ (IO.hPutStrLn IO.stderr . mappend "unknown option " . quote) os+    mapM_ (IO.hPutStr IO.stderr) es+    Monad.unless (null es) Exit.exitFailure++    config <- either fail pure $ Monad.foldM applyFlag defaultConfig flags+    Monad.when (configHelp config) $ do+        putStr $ Console.usageInfo (name <> " version " <> version) options+        Exit.exitSuccess+    Monad.when (configVersion config) $ do+        putStrLn version+        Exit.exitSuccess++    contents <- ByteString.getContents+    case Argo.decode contents of+        Argo.Failure e -> fail e+        Argo.Success value -> Builder.hPutBuilder IO.stdout+            $ Argo.encodeWith (configIndent config) (value :: Argo.Value)++quote :: String -> String+quote x = "`" <> x <> "'"++version :: String+version = Version.showVersion This.version++data Flag+    = FlagHelp+    | FlagSpaces String+    | FlagTab+    | FlagVersion+    deriving (Eq, Show)++options :: [Console.OptDescr Flag]+options =+    [ Console.Option ['h', '?'] ["help"] (Console.NoArg FlagHelp) "shows this help message and exits"+    , Console.Option ['v'] ["version"] (Console.NoArg FlagVersion) "shows the version number and exits"+    , Console.Option ['s'] ["spaces"] (Console.ReqArg FlagSpaces "INT") "pretty-prints the output using INT sapces"+    , Console.Option ['t'] ["tab"] (Console.NoArg FlagTab) "pretty-prints the output using tabs"+    ]++data Config = Config+    { configHelp :: Bool+    , configIndent :: Encoder.Indent+    , configVersion :: Bool+    } deriving (Eq, Show)++defaultConfig :: Config+defaultConfig = Config+    { configHelp = False+    , configIndent = Encoder.Spaces 0+    , configVersion = False+    }++applyFlag :: Config -> Flag -> Either String Config+applyFlag config flag = case flag of+    FlagHelp -> pure config { configHelp = True }+    FlagSpaces string -> do+        int <- Read.readEither string+        pure config { configIndent = Encoder.Spaces int }+    FlagTab -> pure config { configIndent = Encoder.Tab }+    FlagVersion -> pure config { configVersion = True }
source/library/Argo/Pattern.hs view
@@ -2,16 +2,16 @@  module Argo.Pattern where -import qualified Argo.Type as Type-import qualified Argo.Type.Array as Array-import qualified Argo.Type.Boolean as Boolean-import qualified Argo.Type.Null as Null-import qualified Argo.Type.Number as Number-import qualified Argo.Type.Object as Object-import qualified Argo.Type.Pair as Pair-import qualified Argo.Type.String as String-import qualified Argo.Type.Value as Value-import qualified Data.Text as Text+import qualified Argo.Json.Array as Array+import qualified Argo.Json.Boolean as Boolean+import qualified Argo.Json.Member as Member+import qualified Argo.Json.Name as Name+import qualified Argo.Json.Null as Null+import qualified Argo.Json.Number as Number+import qualified Argo.Json.Object as Object+import qualified Argo.Json.String as String+import qualified Argo.Json.Value as Value+import qualified Argo.Vendor.Text as Text  pattern Null :: Value.Value pattern Null = Value.Null (Null.Null ())@@ -26,15 +26,26 @@ pattern String :: Text.Text -> Value.Value pattern String x = Value.String (String.String x) -pattern Array :: Type.Array -> Value.Value+type Array = [Value.Value]++pattern Array :: Array -> Value.Value pattern Array x = Value.Array (Array.Array x) -pattern Object :: Type.Object -> Value.Value+type Object = [Member]++pattern Object :: Object -> Value.Value pattern Object x = Value.Object (Object.Object x)  {-# COMPLETE Null, Boolean, Number, String, Array, Object #-} -pattern Pair :: Text.Text -> Value.Value -> Pair.Pair String.String Value.Value-pattern Pair k v = Pair.Pair (String.String k, v)+type Member = Member.MemberOf Value.Value -{-# COMPLETE Pair #-}+pattern Member :: Name.Name -> Value.Value -> Member+pattern Member k v = Member.Member k v++{-# COMPLETE Member #-}++pattern Name :: Text.Text -> Name.Name+pattern Name x = Name.Name (String.String x)++{-# COMPLETE Name #-}
source/library/Argo/QuasiQuoter.hs view
@@ -1,21 +1,20 @@ module Argo.QuasiQuoter where  import qualified Argo.Decode as Decode+import qualified Argo.Json.Value as Value import qualified Argo.Result as Result-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Language.Haskell.TH.Quote as QQ-import qualified Language.Haskell.TH.Syntax as TH+import qualified Argo.Vendor.TemplateHaskell as TH+import qualified Argo.Vendor.Text as Text -value :: QQ.QuasiQuoter-value = QQ.QuasiQuoter-    { QQ.quoteDec = const $ fail "quoteDec"-    , QQ.quoteExp = quoteExp-    , QQ.quotePat = const $ fail "quotePat"-    , QQ.quoteType = const $ fail "quoteType"+value :: TH.QuasiQuoter+value = TH.QuasiQuoter+    { TH.quoteDec = const $ fail "cannot be used as a declaration"+    , TH.quoteExp = quoteExp+    , TH.quotePat = const $ fail "cannot be used as a pattern"+    , TH.quoteType = const $ fail "cannot be used as a type"     }  quoteExp :: String -> TH.Q TH.Exp-quoteExp x = case Decode.decodeWith pure . Text.encodeUtf8 $ Text.pack x of+quoteExp x = case Decode.decode . Text.encodeUtf8 $ Text.pack x of     Result.Failure e -> fail e-    Result.Success y -> TH.lift y+    Result.Success y -> TH.lift (y :: Value.Value)
− source/library/Argo/Type.hs
@@ -1,10 +0,0 @@-module Argo.Type where--import qualified Argo.Type.Pair as Pair-import qualified Argo.Type.String as String-import qualified Argo.Type.Value as Value-import qualified Data.Array--type Array = Data.Array.Array Int Value.Value--type Object = Data.Array.Array Int (Pair.Pair String.String Value.Value)
− source/library/Argo/Type/Array.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Array where--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Control.DeepSeq as DeepSeq-import qualified Data.Array as Array-import qualified Data.ByteString.Builder as Builder-import qualified Language.Haskell.TH.Syntax as TH--newtype Array a-    = Array (Array.Array Int a)-    deriving (Eq, Show)--instance TH.Lift a => TH.Lift (Array a) where-    liftTyped (Array x) =-        let-            bounds = Array.bounds x-            elems = Array.elems x-        in [|| Array $ Array.listArray bounds elems ||]--instance DeepSeq.NFData a => DeepSeq.NFData (Array a) where-    rnf (Array x) = DeepSeq.rnf x--encode :: (a -> Builder.Builder) -> Array a -> Builder.Builder-encode f (Array x) =-    Builder.word8 Literal.leftSquareBracket-    <> foldMap-        (\ (i, e) -> (if i /= 0 then Builder.word8 Literal.comma else mempty)-            <> f e)-        (Array.assocs x)-    <> Builder.word8 Literal.rightSquareBracket--decode :: Decoder.Decoder a -> Decoder.Decoder (Array a)-decode f = do-    Decoder.word8 Literal.leftSquareBracket-    Decoder.spaces-    xs <- Decoder.array f-    Decoder.word8 Literal.rightSquareBracket-    Decoder.spaces-    pure $ Array xs
− source/library/Argo/Type/Boolean.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Boolean where--import Control.Applicative ((<|>))--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Control.DeepSeq as DeepSeq-import qualified Data.ByteString.Builder as Builder-import qualified Language.Haskell.TH.Syntax as TH--newtype Boolean-    = Boolean Bool-    deriving (Eq, Show)--instance TH.Lift Boolean where-    liftTyped (Boolean x) = [|| Boolean x ||]--instance DeepSeq.NFData Boolean where-    rnf (Boolean x) = DeepSeq.rnf x--encode :: Boolean -> Builder.Builder-encode (Boolean x) =-    Builder.byteString $ if x then Literal.true else Literal.false--decode :: Decoder.Decoder Boolean-decode = decodeFalse <|> decodeTrue--decodeFalse :: Decoder.Decoder Boolean-decodeFalse = Boolean False <$ Decoder.byteString Literal.false <* Decoder.spaces--decodeTrue :: Decoder.Decoder Boolean-decodeTrue = Boolean True <$ Decoder.byteString Literal.true <* Decoder.spaces
− source/library/Argo/Type/Null.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Null where--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Control.DeepSeq as DeepSeq-import qualified Data.ByteString.Builder as Builder-import qualified Language.Haskell.TH.Syntax as TH--newtype Null-    = Null ()-    deriving (Eq, Show)--instance TH.Lift Null where-    liftTyped (Null x) = [|| Null x ||]--instance DeepSeq.NFData Null where-    rnf (Null x) = DeepSeq.rnf x--encode :: Null -> Builder.Builder-encode = const $ Builder.byteString Literal.null--decode :: Decoder.Decoder Null-decode = Null () <$ Decoder.byteString Literal.null <* Decoder.spaces
− source/library/Argo/Type/Number.hs
@@ -1,109 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Number where--import Data.Ratio ((%))--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Control.Applicative as Applicative-import qualified Control.DeepSeq as DeepSeq-import qualified Control.Monad as Monad-import qualified Data.Bool as Bool-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Builder as Builder-import qualified Data.Maybe as Maybe-import qualified Data.Ratio as Ratio-import qualified Data.Word as Word-import qualified Language.Haskell.TH.Syntax as TH--data Number-    = Number Integer Integer-    deriving (Eq, Show)--instance TH.Lift Number where-    liftTyped (Number x y) = [|| Number x y ||]--instance DeepSeq.NFData Number where-    rnf (Number x y) = DeepSeq.deepseq x $ DeepSeq.rnf y--number :: Integer -> Integer -> Number-number x = normalize . Number x--normalize :: Number -> Number-normalize (Number x y) =-    if x == 0-    then Number 0 0-    else let (q, r) = quotRem x 10 in if r == 0-    then normalize $ Number q (y + 1)-    else Number x y--encode :: Number -> Builder.Builder-encode (Number x y) =-    if y == 0-    then Builder.integerDec x-    else Builder.integerDec x-        <> Builder.word8 Literal.latinSmallLetterE-        <> Builder.integerDec y--decode :: Decoder.Decoder Number-decode = do-    ni <- fmap Maybe.isJust . Applicative.optional $ Decoder.word8 Literal.hyphenMinus-    i <- Decoder.takeWhile1 Decoder.isDigit-    Monad.when (ByteString.length i > 1 && ByteString.elemIndex Literal.digitZero i == Just 0)-        $ fail "leading zero"-    f <- fmap (Maybe.fromMaybe ByteString.empty) . Applicative.optional $ do-        Decoder.word8 Literal.fullStop-        Decoder.takeWhile1 Decoder.isDigit-    (ne, e) <- fmap (Maybe.fromMaybe (False, ByteString.empty)) . Applicative.optional $ do-        Monad.void-            . Decoder.satisfy-            $ \ x -> x == Literal.latinSmallLetterE || x == Literal.latinCapitalLetterE-        ne <- fmap (== Just Literal.hyphenMinus)-            . Applicative.optional-            . Decoder.satisfy-            $ \ x -> x == Literal.hyphenMinus || x == Literal.plusSign-        e <- Decoder.takeWhile1 Decoder.isDigit-        pure (ne, e)-    Decoder.spaces-    pure $ number-        (negateIf ni $ (fromDigits i * 10 ^ ByteString.length f) + fromDigits f)-        (negateIf ne (fromDigits e) - intToInteger (ByteString.length f))--negateIf :: Bool -> Integer -> Integer-negateIf = Bool.bool id negate--fromDigits :: ByteString.ByteString -> Integer-fromDigits = ByteString.foldl' (\ a e -> (a * 10) + word8ToInteger (e - 0x30)) 0--intToInteger :: Int -> Integer-intToInteger = fromIntegral--word8ToInteger :: Word.Word8 -> Integer-word8ToInteger = fromIntegral--toRational :: Number -> Rational-toRational (Number x y) =-    if y < 0-    then x % (10 ^ (-y))-    else fromInteger $ x * 10 ^ y--fromRational :: Rational -> Maybe Number-fromRational r =-    let-        n = Ratio.numerator r-        d1 = Ratio.denominator r-        (t, d2) = factor 2 (0 :: Integer) d1-        (f, d3) = factor 5 (0 :: Integer) d2-        p = max t f-    in if d3 == 1-    then Just $ number (n * 2 ^ (p - t) * 5 ^ (p - f)) (-p)-    else Nothing---- factor d 0 x = (p, y) <=> x = (d ^ p) * y-factor :: (Num a, Integral b) => b -> a -> b -> (a, b)-factor d n x =-    let (q, r) = quotRem x d-    in if x /= 0 && r == 0-    then factor d (n + 1) q-    else (n, x)
− source/library/Argo/Type/Object.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Object where--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Argo.Type.Pair as Pair-import qualified Argo.Type.String as String-import qualified Control.DeepSeq as DeepSeq-import qualified Data.Array as Array-import qualified Data.ByteString.Builder as Builder-import qualified Language.Haskell.TH.Syntax as TH--newtype Object a-    = Object (Array.Array Int (Pair.Pair String.String a))-    deriving (Eq, Show)--instance TH.Lift a => TH.Lift (Object a) where-    liftTyped (Object x) =-        let-            bounds = Array.bounds x-            elems = Array.elems x-        in [|| Object $ Array.listArray bounds elems ||]--instance DeepSeq.NFData a => DeepSeq.NFData (Object a) where-    rnf (Object x) = DeepSeq.rnf x--encode :: (a -> Builder.Builder) -> Object a -> Builder.Builder-encode f (Object x) =-    Builder.word8 Literal.leftCurlyBracket-    <> foldMap-        (\ (i, e) -> (if i /= 0 then Builder.word8 Literal.comma else mempty)-            <> Pair.encode String.encode f e)-        (Array.assocs x)-    <> Builder.word8 Literal.rightCurlyBracket--decode :: Decoder.Decoder a -> Decoder.Decoder (Object a)-decode f = do-    Decoder.word8 Literal.leftCurlyBracket-    Decoder.spaces-    xs <- Decoder.array $ Pair.decode String.decode f-    Decoder.word8 Literal.rightCurlyBracket-    Decoder.spaces-    pure $ Object xs
− source/library/Argo/Type/Pair.hs
@@ -1,33 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Pair where--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Control.DeepSeq as DeepSeq-import qualified Data.ByteString.Builder as Builder-import qualified Language.Haskell.TH.Syntax as TH--newtype Pair k v-    = Pair (k, v)-    deriving (Eq, Show)--instance (TH.Lift k, TH.Lift v) => TH.Lift (Pair k v) where-    liftTyped (Pair x) = [|| Pair x ||]--instance (DeepSeq.NFData k, DeepSeq.NFData v) => DeepSeq.NFData (Pair k v) where-    rnf (Pair x) = DeepSeq.rnf x--encode :: (k -> Builder.Builder) -> (v -> Builder.Builder) -> Pair k v -> Builder.Builder-encode f g (Pair (x, y)) =-    f x-    <> Builder.word8 Literal.colon-    <> g y--decode :: Decoder.Decoder k -> Decoder.Decoder v -> Decoder.Decoder (Pair k v)-decode f g = do-    k <- f-    Decoder.word8 Literal.colon-    Decoder.spaces-    v <- g-    pure $ Pair (k, v)
− source/library/Argo/Type/String.hs
@@ -1,145 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.String where--import qualified Argo.Decoder as Decoder-import qualified Argo.Literal as Literal-import qualified Control.DeepSeq as DeepSeq-import qualified Control.Monad as Monad-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Builder as Builder-import qualified Data.ByteString.Builder.Prim as P-import qualified Data.Char as Char-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Data.Word as Word-import qualified Language.Haskell.TH.Syntax as TH--newtype String-    = String Text.Text-    deriving (Eq, Show)--instance TH.Lift Argo.Type.String.String where-    liftTyped (String x) = [|| String x ||]--instance DeepSeq.NFData Argo.Type.String.String where-    rnf (String x) = DeepSeq.rnf x--encode :: Argo.Type.String.String -> Builder.Builder-encode (String x) =-    Builder.word8 Literal.quotationMark-    <> Text.encodeUtf8BuilderEscaped encodeChar x-    <> Builder.word8 Literal.quotationMark--encodeChar :: P.BoundedPrim Word.Word8-encodeChar =-    P.condB (== Literal.quotationMark) (encodeShortEscape Literal.quotationMark)-    . P.condB (== Literal.reverseSolidus) (encodeShortEscape Literal.reverseSolidus)-    . P.condB (== Literal.backspace) (encodeShortEscape Literal.latinSmallLetterB)-    . P.condB (== Literal.formFeed) (encodeShortEscape Literal.latinSmallLetterF)-    . P.condB (== Literal.newLine) (encodeShortEscape Literal.latinSmallLetterN)-    . P.condB (== Literal.carriageReturn) (encodeShortEscape Literal.latinSmallLetterR)-    . P.condB (== Literal.horizontalTabulation) (encodeShortEscape Literal.latinSmallLetterT)-    . P.condB (< Literal.space) encodeLongEscape-    $ P.liftFixedToBounded P.word8--encodeShortEscape :: Word.Word8 -> P.BoundedPrim a-encodeShortEscape x = P.liftFixedToBounded-    $ const (Literal.reverseSolidus, x)-    P.>$< P.word8-    P.>*< P.word8--encodeLongEscape :: P.BoundedPrim Word.Word8-encodeLongEscape = P.liftFixedToBounded-    $ (\ x -> (Literal.reverseSolidus, (Literal.latinSmallLetterU, word8ToWord16 x)))-    P.>$< P.word8-    P.>*< P.word8-    P.>*< P.word16HexFixed--word8ToWord16 :: Word.Word8 -> Word.Word16-word8ToWord16 = fromIntegral--decode :: Decoder.Decoder Argo.Type.String.String-decode = do-    Decoder.word8 Literal.quotationMark-    b1 <- Decoder.get-    i <- case getClose b1 0 of-        Nothing -> fail "unterminated string"-        Just i -> pure i-    let (xs, b2) = ByteString.splitAt i b1-    Monad.when (ByteString.any (< Literal.space) xs) $ fail "unescaped control character"-    Decoder.put b2-    Decoder.word8 Literal.quotationMark-    Decoder.spaces-    case Text.decodeUtf8' xs of-        Left e -> fail $ show e-        Right x -> case unescapeText x of-            Nothing -> fail "invalid escape"-            Just y -> pure $ String y--findAt :: Word.Word8 -> Int -> ByteString.ByteString -> Maybe Int-findAt x i = fmap (+ i) . ByteString.elemIndex x . ByteString.drop i--countConsecutive :: Word.Word8 -> Int -> ByteString.ByteString -> Int-countConsecutive x i = ByteString.length . ByteString.takeWhileEnd (== x) . ByteString.take i--getClose :: ByteString.ByteString -> Int -> Maybe Int-getClose b i = do-    j <- findAt Literal.quotationMark i b-    let n = countConsecutive Literal.reverseSolidus j b-    if even n then Just j else getClose b $ j + 1--unescapeText :: Text.Text -> Maybe Text.Text-unescapeText = fmap (Text.pack . combineSurrogatePairs) . unescapeString . Text.unpack--combineSurrogatePairs :: Prelude.String -> Prelude.String-combineSurrogatePairs xs = case xs of-    "" -> xs-    x : y : zs | isHighSurrogate x && isLowSurrogate y ->-        combineSurrogatePair x y : combineSurrogatePairs zs-    x : ys -> x : combineSurrogatePairs ys--combineSurrogatePair :: Char -> Char -> Char-combineSurrogatePair hi lo = Char.chr-    $ 0x10000-    + ((Char.ord hi - 0xd800) * 0x400)-    + (Char.ord lo - 0xdc00)--isHighSurrogate :: Char -> Bool-isHighSurrogate x = '\xd800' <= x && x <= '\xdbff'--isLowSurrogate :: Char -> Bool-isLowSurrogate x = '\xdc00' <= x && x <= '\xdfff'--unescapeString :: Prelude.String -> Maybe Prelude.String-unescapeString xs = case xs of-    "" -> pure xs-    '\\' : ys -> case ys of-        "" -> fail "empty escape"-        x : zs -> case x of-            '"' -> ('"' :) <$> unescapeString zs-            '\\' -> ('\\' :) <$> unescapeString zs-            '/' -> ('/' :) <$> unescapeString zs-            'b' -> ('\b' :) <$> unescapeString zs-            'f' -> ('\f' :) <$> unescapeString zs-            'n' -> ('\n' :) <$> unescapeString zs-            'r' -> ('\r' :) <$> unescapeString zs-            't' -> ('\t' :) <$> unescapeString zs-            'u' -> case zs of-                a : b : c : d : es | Just y <- fromLongEscape a b c d ->-                    (y :) <$> unescapeString es-                _ -> fail "invalid long escape"-            _ -> fail "invalid short escape"-    x : ys -> (x :) <$> unescapeString ys--fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char-fromLongEscape a b c d = do-    w <- fromHexadecimalDigit a-    x <- fromHexadecimalDigit b-    y <- fromHexadecimalDigit c-    z <- fromHexadecimalDigit d-    pure . Char.chr $ (0x1000 * w) + (0x100 * x) + (0x10 * y) + z--fromHexadecimalDigit :: Char -> Maybe Int-fromHexadecimalDigit x =-    if Char.isHexDigit x then Just $ Char.digitToInt x else Nothing
− source/library/Argo/Type/Value.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE TemplateHaskellQuotes #-}--module Argo.Type.Value where--import Control.Applicative ((<|>))--import qualified Argo.Decoder as Decoder-import qualified Argo.Type.Array as Array-import qualified Argo.Type.Boolean as Boolean-import qualified Argo.Type.Null as Null-import qualified Argo.Type.Number as Number-import qualified Argo.Type.Object as Object-import qualified Argo.Type.String as String-import qualified Control.DeepSeq as DeepSeq-import qualified Data.ByteString.Builder as Builder-import qualified Language.Haskell.TH.Syntax as TH--data Value-    = Null Null.Null-    | Boolean Boolean.Boolean-    | Number Number.Number-    | String String.String-    | Array (Array.Array Value)-    | Object (Object.Object Value)-    deriving (Eq, Show)--instance TH.Lift Value where-    liftTyped x = case x of-        Null y -> [|| Null y ||]-        Boolean y -> [|| Boolean y ||]-        Number y -> [|| Number y ||]-        String y -> [|| String y ||]-        Array y -> [|| Array y ||]-        Object y -> [|| Object y ||]--instance DeepSeq.NFData Value where-    rnf x = case x of-        Null y -> DeepSeq.rnf y-        Boolean y -> DeepSeq.rnf y-        Number y -> DeepSeq.rnf y-        String y -> DeepSeq.rnf y-        Array y -> DeepSeq.rnf y-        Object y -> DeepSeq.rnf y--encode :: Value -> Builder.Builder-encode x = case x of-    Null y -> Null.encode y-    Boolean y -> Boolean.encode y-    Number y -> Number.encode y-    String y -> String.encode y-    Array y -> Array.encode encode y-    Object y -> Object.encode encode y--decode :: Decoder.Decoder Value-decode =-    Null <$> Null.decode-    <|> Boolean <$> Boolean.decode-    <|> Number <$> Number.decode-    <|> String <$> String.decode-    <|> Array <$> Array.decode decode-    <|> Object <$> Object.decode decode
+ source/library/Argo/Vendor/Builder.hs view
@@ -0,0 +1,20 @@+module Argo.Vendor.Builder+    ( Prim.BoundedPrim+    , Builder.Builder+    , Builder.byteString+    , Prim.condB+    , Builder.integerDec+    , Prim.liftFixedToBounded+    , Builder.word8+    , word8F+    , Prim.word16HexFixed+    , (Prim.>$<)+    , (Prim.>*<)+    ) where++import qualified Data.ByteString.Builder as Builder+import qualified Data.ByteString.Builder.Prim as Prim+import qualified Data.Word as Word++word8F :: Prim.FixedPrim Word.Word8+word8F = Prim.word8
+ source/library/Argo/Vendor/ByteString.hs view
@@ -0,0 +1,20 @@+module Argo.Vendor.ByteString+    ( ByteString.ByteString+    , ByteString.any+    , ByteString.drop+    , ByteString.dropWhile+    , ByteString.elemIndex+    , ByteString.empty+    , ByteString.foldl'+    , ByteString.length+    , ByteString.null+    , ByteString.pack+    , ByteString.span+    , ByteString.splitAt+    , ByteString.stripPrefix+    , ByteString.take+    , ByteString.takeWhileEnd+    , ByteString.uncons+    ) where++import qualified Data.ByteString as ByteString
+ source/library/Argo/Vendor/DeepSeq.hs view
@@ -0,0 +1,6 @@+module Argo.Vendor.DeepSeq+    ( DeepSeq.NFData(..)+    , DeepSeq.deepseq+    ) where++import qualified Control.DeepSeq as DeepSeq
+ source/library/Argo/Vendor/TemplateHaskell.hs view
@@ -0,0 +1,9 @@+module Argo.Vendor.TemplateHaskell+    ( TH.Exp+    , TH.Lift(..)+    , TH.Q+    , QQ.QuasiQuoter(..)+    ) where++import qualified Language.Haskell.TH.Quote as QQ+import qualified Language.Haskell.TH.Syntax as TH
+ source/library/Argo/Vendor/Text.hs view
@@ -0,0 +1,20 @@+module Argo.Vendor.Text+    ( LazyText+    , Text.Text+    , Encoding.decodeUtf8'+    , Encoding.encodeUtf8+    , Encoding.encodeUtf8BuilderEscaped+    , LazyText.fromStrict+    , Text.null+    , Text.pack+    , Text.singleton+    , LazyText.toStrict+    , Text.uncons+    , Text.unpack+    ) where++import qualified Data.Text as Text+import qualified Data.Text.Encoding as Encoding+import qualified Data.Text.Lazy as LazyText++type LazyText = LazyText.Text
+ source/library/Argo/Vendor/Transformers.hs view
@@ -0,0 +1,15 @@+module Argo.Vendor.Transformers+    ( ReaderT.ReaderT+    , WriterT.WriterT+    , ReaderT.ask+    , ReaderT.asks+    , WriterT.execWriterT+    , Trans.lift+    , ReaderT.local+    , ReaderT.runReaderT+    , WriterT.tell+    ) where++import qualified Control.Monad.Trans.Class as Trans+import qualified Control.Monad.Trans.Reader as ReaderT+import qualified Control.Monad.Trans.Writer as WriterT
source/test-suite/Main.hs view
@@ -4,15 +4,17 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} +import Data.GenValidity.Map ()+import Data.GenValidity.Text () import Data.List.NonEmpty (NonEmpty((:|))) import Test.Tasty.HUnit ((@?=)) import Test.Tasty.QuickCheck ((===))  import qualified Argo-import qualified Data.Array as Array import qualified Data.ByteString as ByteString import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Lazy as LazyByteString+import qualified Data.GenValidity as GenValidity import qualified Data.Int as Int import qualified Data.Map as Map import qualified Data.Text as Text@@ -87,19 +89,19 @@             ]         , Tasty.testGroup "Array"             [ Tasty.testCase "empty" $ do-                encode (Argo.Array (array [])) @?= "[]"+                encode (Argo.Array []) @?= "[]"             , Tasty.testCase "one element" $ do-                encode (Argo.Array (array [Argo.Number 1 0])) @?= "[1]"+                encode (Argo.Array [Argo.Number 1 0]) @?= "[1]"             , Tasty.testCase "two elements" $ do-                encode (Argo.Array (array [Argo.Number 1 0, Argo.Number 2 0])) @?= "[1,2]"+                encode (Argo.Array [Argo.Number 1 0, Argo.Number 2 0]) @?= "[1,2]"             ]         , Tasty.testGroup "Object"             [ Tasty.testCase "empty" $ do-                encode (Argo.Object (array [])) @?= "{}"+                encode (Argo.Object []) @?= "{}"             , Tasty.testCase "one element" $ do-                encode (Argo.Object (array [Argo.Pair "a" $ Argo.Number 1 0])) @?= "{\"a\":1}"+                encode (Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Number 1 0]) @?= "{\"a\":1}"             , Tasty.testCase "two elements" $ do-                encode (Argo.Object (array [Argo.Pair "a" $ Argo.Number 1 0, Argo.Pair "b" $ Argo.Number 2 0])) @?= "{\"a\":1,\"b\":2}"+                encode (Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Number 1 0, Argo.Member (Argo.Name "b") $ Argo.Number 2 0]) @?= "{\"a\":1,\"b\":2}"             ]         ]     , Tasty.testGroup "decode" $ let decode = resultToMaybe . Argo.decode :: ByteString.ByteString -> Maybe Argo.Value in@@ -239,13 +241,13 @@             ]         , Tasty.testGroup "Array"             [ Tasty.testCase "empty" $ do-                decode "[]" @?= Just (Argo.Array $ array [])+                decode "[]" @?= Just (Argo.Array [])             , Tasty.testCase "one element" $ do-                decode "[1]" @?= Just (Argo.Array $ array [Argo.Number 1 0])+                decode "[1]" @?= Just (Argo.Array [Argo.Number 1 0])             , Tasty.testCase "two elements" $ do-                decode "[1,2]" @?= Just (Argo.Array $ array [Argo.Number 1 0, Argo.Number 2 0])+                decode "[1,2]" @?= Just (Argo.Array [Argo.Number 1 0, Argo.Number 2 0])             , Tasty.testCase "nested" $ do-                decode "[1,[2]]" @?= Just (Argo.Array $ array [Argo.Number 1 0, Argo.Array $ array [Argo.Number 2 0]])+                decode "[1,[2]]" @?= Just (Argo.Array [Argo.Number 1 0, Argo.Array [Argo.Number 2 0]])             , Tasty.testCase "not closed" $ do                 decode "[" @?= Nothing             , Tasty.testCase "not opened" $ do@@ -261,13 +263,13 @@             ]         , Tasty.testGroup "Object"             [ Tasty.testCase "empty" $ do-                decode "{}" @?= Just (Argo.Object $ array [])+                decode "{}" @?= Just (Argo.Object [])             , Tasty.testCase "one element" $ do-                decode "{\"a\":1}" @?= Just (Argo.Object $ array [Argo.Pair "a" $ Argo.Number 1 0])+                decode "{\"a\":1}" @?= Just (Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Number 1 0])             , Tasty.testCase "two elements" $ do-                decode "{\"a\":1,\"b\":2}" @?= Just (Argo.Object $ array [Argo.Pair "a" $ Argo.Number 1 0, Argo.Pair "b" $ Argo.Number 2 0])+                decode "{\"a\":1,\"b\":2}" @?= Just (Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Number 1 0, Argo.Member (Argo.Name "b") $ Argo.Number 2 0])             , Tasty.testCase "nested" $ do-                decode "{\"a\":{\"b\":2}}" @?= Just (Argo.Object $ array [Argo.Pair "a" . Argo.Object $ array [Argo.Pair "b" $ Argo.Number 2 0]])+                decode "{\"a\":{\"b\":2}}" @?= Just (Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Object [Argo.Member (Argo.Name "b") $ Argo.Number 2 0]])             , Tasty.testCase "not closed" $ do                 decode "{" @?= Nothing             , Tasty.testCase "not opened" $ do@@ -338,17 +340,15 @@         , Tasty.testCase "Maybe a" $ do             fromValue (Argo.Boolean False) @?= Just (Just False)         , Tasty.testCase "()" $ do-            fromValue (Argo.Array $ array []) @?= Just ()+            fromValue (Argo.Array []) @?= Just ()         , Tasty.testCase "(a, b)" $ do-            fromValue (Argo.Array $ array [Argo.Boolean False, Argo.String "a"]) @?= Just (False, 'a')-        , Tasty.testCase "Array Int a" $ do-            fromValue (Argo.Array $ array []) @?= Just (array [] :: Array.Array Int Bool)+            fromValue (Argo.Array [Argo.Boolean False, Argo.String "a"]) @?= Just (False, 'a')         , Tasty.testCase "[a]" $ do-            fromValue (Argo.Array $ array []) @?= Just ([] :: [Bool])+            fromValue (Argo.Array []) @?= Just ([] :: [Bool])         , Tasty.testCase "NonEmpty a" $ do-            fromValue (Argo.Array $ array [Argo.Boolean False]) @?= Just (False :| [])+            fromValue (Argo.Array [Argo.Boolean False]) @?= Just (False :| [])         , Tasty.testCase "Map Text a" $ do-            fromValue (Argo.Object $ array [Argo.Pair "a" $ Argo.Boolean False]) @?= Just (Map.fromList [("a" :: Text.Text, False)])+            fromValue (Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Boolean False]) @?= Just (Map.fromList [("a" :: Text.Text, False)])         ]     , Tasty.testGroup "toValue"         [ Tasty.testCase "Value" $ do@@ -392,17 +392,15 @@         , Tasty.testCase "Maybe a" $ do             Argo.toValue (Just False) @?= Argo.Boolean False         , Tasty.testCase "()" $ do-            Argo.toValue () @?= Argo.Array (array [])+            Argo.toValue () @?= Argo.Array []         , Tasty.testCase "(a, b)" $ do-            Argo.toValue (False, 'a') @?= Argo.Array (array [Argo.Boolean False, Argo.String "a"])-        , Tasty.testCase "Array Int a" $ do-            Argo.toValue (array [] :: Array.Array Int Bool) @?= Argo.Array (array [])+            Argo.toValue (False, 'a') @?= Argo.Array [Argo.Boolean False, Argo.String "a"]         , Tasty.testCase "[a]" $ do-            Argo.toValue ([] :: [Bool]) @?= Argo.Array (array [])+            Argo.toValue ([] :: [Bool]) @?= Argo.Array []         , Tasty.testCase "NonEmpty a" $ do-            Argo.toValue (False :| []) @?= Argo.Array (array [Argo.Boolean False])+            Argo.toValue (False :| []) @?= Argo.Array [Argo.Boolean False]         , Tasty.testCase "Map Text a" $ do-            Argo.toValue (Map.fromList [("a" :: Text.Text, False)]) @?= Argo.Object (array [Argo.Pair "a" $ Argo.Boolean False])+            Argo.toValue (Map.fromList [("a" :: Text.Text, False)]) @?= Argo.Object [Argo.Member (Argo.Name "a") $ Argo.Boolean False]         ]     , Tasty.testGroup "quasi quoter"         [ Tasty.testCase "Null" $ do@@ -414,120 +412,138 @@         , Tasty.testCase "String" $ do             [Argo.value| "" |] @?= Argo.String ""         , Tasty.testCase "Array" $ do-            [Argo.value| [] |] @?= Argo.Array (array [])+            [Argo.value| [] |] @?= Argo.Array []         , Tasty.testCase "Object" $ do-            [Argo.value| {} |] @?= Argo.Object (array [])+            [Argo.value| {} |] @?= Argo.Object []         ]     , Tasty.testGroup "property"-        [ Tasty.testProperty "decode . encode" . Tasty.forAll genValue $ \ x -> Tasty.shrinking shrinkValue x $ \ y ->-            (resultToMaybe . Argo.decode . LazyByteString.toStrict . Builder.toLazyByteString $ Argo.encode y) === Just y+        [ property "decode . encode" $ \ x ->+            (resultToMaybe . Argo.decode . LazyByteString.toStrict . Builder.toLazyByteString $ Argo.encode x) === Just (x :: Argo.Value)+        , property "decode . encodeWith" $ \ x ->+            (Argo.decode . LazyByteString.toStrict . Builder.toLazyByteString $ Argo.encodeWith Argo.Tab x) === Argo.Success (x :: Argo.Value)         , Tasty.testGroup "fromValue . toValue"-            [ Tasty.testProperty "Value" . Tasty.forAll genValue $ \ x -> Tasty.shrinking shrinkValue x $ \ y ->-                (resultToMaybe . Argo.fromValue $ Argo.toValue y) === Just y-            , Tasty.testProperty "Bool" $ \ x ->+            [ property "Value" $ \ x ->+                (resultToMaybe . Argo.fromValue $ Argo.toValue x) === Just (x :: Argo.Value)+            , property "Bool" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Bool)-            , Tasty.testProperty "Char" $ \ x ->-                Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Char)-            , Tasty.testProperty "Int" $ \ x ->+            , property "Char" $ \ x ->+                Argo.fromValue (Argo.toValue x) === if '\xd800' <= x && x <= '\xdfff'+                    then Argo.Success '\xfffd'+                    else Argo.Success x+            , property "Int" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Int)-            , Tasty.testProperty "Int8" $ \ x ->+            , property "Int8" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Int.Int8)-            , Tasty.testProperty "Int16" $ \ x ->+            , property "Int16" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Int.Int16)-            , Tasty.testProperty "Int32" $ \ x ->+            , property "Int32" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Int.Int32)-            , Tasty.testProperty "Int64" $ \ x ->+            , property "Int64" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Int.Int64)-            , Tasty.testProperty "Word" $ \ x ->+            , property "Word" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Word)-            , Tasty.testProperty "Word8" $ \ x ->+            , property "Word8" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Word.Word8)-            , Tasty.testProperty "Word16" $ \ x ->+            , property "Word16" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Word.Word16)-            , Tasty.testProperty "Word32" $ \ x ->+            , property "Word32" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Word.Word32)-            , Tasty.testProperty "Word64" $ \ x ->+            , property "Word64" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Word.Word64)-            , Tasty.testProperty "Integer" $ \ x ->+            , property "Integer" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Integer)-            , Tasty.testProperty "Float" $ \ x ->-                Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Float)-            , Tasty.testProperty "Double" $ \ x ->-                Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Double)-            , Tasty.testProperty "String" $ \ x ->-                Argo.fromValue (Argo.toValue x) === Argo.Success (x :: String)-            , Tasty.testProperty "Text" $ \ x ->+            , property "Float" $ \ x ->+                Argo.fromValue (Argo.toValue x) === if isNaN x || isInfinite x+                    then Argo.Failure "expected Float but got Null (Null ())"+                    else Argo.Success (x :: Float)+            , property "Double" $ \ x ->+                Argo.fromValue (Argo.toValue x) === if isNaN x || isInfinite x+                    then Argo.Failure "expected Double but got Null (Null ())"+                    else Argo.Success (x :: Double)+            , property "String" $ \ x ->+                Argo.fromValue (Argo.toValue x) === Argo.Success (Text.unpack $ Text.pack x)+            , property "Text" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Text.Text)-            , Tasty.testProperty "LazyText" $ \ x ->+            , property "LazyText" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: LazyText.Text)-            , Tasty.testProperty "Maybe a" $ \ x ->+            , property "Maybe a" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Maybe Bool)-            , Tasty.testProperty "()" $ \ x ->+            , property "()" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: ())-            , Tasty.testProperty "(a, b)" $ \ x ->+            , property "(a, b)" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: (Bool, Int.Int8))-            , Tasty.testProperty "Array Int a" $ \ x ->-                Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Array.Array Int Bool)-            , Tasty.testProperty "[a]" $ \ x ->+            , property "[a]" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: [Bool])-            , Tasty.testProperty "NonEmpty a" $ \ x ->+            , property "NonEmpty a" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: NonEmpty Bool)-            , Tasty.testProperty "Map Text a" $ \ x ->+            , property "Map Text a" $ \ x ->                 Argo.fromValue (Argo.toValue x) === Argo.Success (x :: Map.Map Text.Text Bool)             ]         ]     ] -array :: [a] -> Array.Array Int a-array xs = Array.listArray (0, length xs - 1) xs+property+    :: (Show t, Tasty.Testable prop, GenValidity.GenValid t)+    => Tasty.TestName+    -> (t -> prop)+    -> Tasty.TestTree+property n = propertyWith n GenValidity.genValid GenValidity.shrinkValid -genValue :: Tasty.Gen Argo.Value-genValue = Tasty.sized genValueSized+propertyWith+    :: (Show t, Tasty.Testable prop)+    => Tasty.TestName+    -> Tasty.Gen t+    -> (t -> [t])+    -> (t -> prop)+    -> Tasty.TestTree+propertyWith n g s f = Tasty.testProperty n+    . Tasty.forAll g+    $ \ x -> Tasty.shrinking s x f -genValueSized :: Int -> Tasty.Gen Argo.Value-genValueSized size = let newSize = div size 3 in Tasty.oneof-    [ pure Argo.Null-    , Argo.Boolean <$> Tasty.arbitrary-    , Argo.Number <$> Tasty.arbitrary <*> Tasty.arbitrary-    , Argo.String <$> Tasty.arbitrary-    , Argo.Array <$> genArray size (genValueSized newSize)-    , Argo.Object <$> genArray size (Argo.Pair <$> Tasty.arbitrary <*> genValueSized newSize)-    ]+instance GenValidity.Validity Argo.Name where+    validate (Argo.Name x) = GenValidity.validate x -genArray :: Int -> Tasty.Gen a -> Tasty.Gen (Array.Array Int a)-genArray n = fmap (Array.listArray (0, n - 1)) . Tasty.vectorOf n+instance GenValidity.GenValid Argo.Name where+    genValid = Argo.Name <$> GenValidity.genValid+    shrinkValid (Argo.Name x) = Argo.Name <$> GenValidity.shrinkValid x -type Shrink a = a -> [a]+instance GenValidity.Validity Argo.Member where+    validate (Argo.Member k v) = GenValidity.validate (k, v) -shrinkValue :: Shrink Argo.Value-shrinkValue x = case x of-    Argo.Null -> []-    Argo.Boolean y -> Argo.Boolean <$> Tasty.shrink y-    Argo.Number y z -> uncurry Argo.Number <$> Tasty.shrink (y, z)-    Argo.String y -> Argo.String <$> Tasty.shrink y-    Argo.Array y -> Argo.Array <$> shrinkArray shrinkValue y-    Argo.Object y -> Argo.Object <$> shrinkArray (\ (Argo.Pair k v) -> Argo.Pair <$> Tasty.shrink k <*> shrinkValue v) y+instance GenValidity.GenValid Argo.Member where+    genValid = Argo.Member <$> GenValidity.genValid <*> GenValidity.genValid+    shrinkValid (Argo.Member k v) = uncurry Argo.Member <$> GenValidity.shrinkValid (k, v) -shrinkArray :: Shrink a -> Shrink (Array.Array Int a)-shrinkArray = Tasty.shrinkMapBy array Array.elems . Tasty.shrinkList+instance GenValidity.Validity Argo.Value where+    validate x = case x of+        Argo.Null -> GenValidity.valid+        Argo.Boolean y -> GenValidity.annotate y "Boolean"+        Argo.Number y z -> GenValidity.annotate (y, z) "Number"+        Argo.String y -> GenValidity.annotate y "String"+        Argo.Array y -> GenValidity.annotate y "Array"+        Argo.Object y -> GenValidity.annotate y "Object" +instance GenValidity.GenValid Argo.Value where+    genValid = Tasty.sized genValueSized+    shrinkValid x = case x of+        Argo.Null -> []+        Argo.Boolean y -> Argo.Boolean <$> GenValidity.shrinkValid y+        Argo.Number y z -> uncurry Argo.Number <$> GenValidity.shrinkValid (y, z)+        Argo.String y -> Argo.String <$> GenValidity.shrinkValid y+        Argo.Array y -> Argo.Array <$> GenValidity.shrinkValid y+        Argo.Object y -> Argo.Object <$> GenValidity.shrinkValid y++genValueSized :: Int -> Tasty.Gen Argo.Value+genValueSized size = let newSize = div size 3 in Tasty.oneof+    [ pure Argo.Null+    , Argo.Boolean <$> GenValidity.genValid+    , Argo.Number <$> GenValidity.genValid <*> GenValidity.genValid+    , Argo.String <$> GenValidity.genValid+    , Argo.Array <$> Tasty.vectorOf size (genValueSized newSize)+    , Argo.Object <$> Tasty.vectorOf size (Argo.Member <$> GenValidity.genValid <*> genValueSized newSize)+    ]+ resultToMaybe :: Argo.Result a -> Maybe a resultToMaybe r = case r of     Argo.Failure _ -> Nothing     Argo.Success x -> Just x--instance Tasty.Arbitrary Text.Text where-    arbitrary = Text.pack <$> Tasty.arbitrary-    shrink = Tasty.shrinkMap Text.pack Text.unpack--instance Tasty.Arbitrary LazyText.Text where-    arbitrary = LazyText.pack <$> Tasty.arbitrary-    shrink = Tasty.shrinkMap LazyText.pack LazyText.unpack--instance Tasty.Arbitrary a => Tasty.Arbitrary (NonEmpty a) where-    arbitrary = (:|) <$> Tasty.arbitrary <*> Tasty.arbitrary-    shrink (x :| xs) = uncurry (:|) <$> Tasty.shrink (x, xs)--instance Tasty.Arbitrary a => Tasty.Arbitrary (Array.Array Int a) where-    arbitrary = array <$> Tasty.arbitrary-    shrink = Tasty.shrinkMap array Array.elems