cretheus 1.0.0 → 1.1.0
raw patch · 6 files changed
+86/−26 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Cretheus.Decode: integer :: Decoder Integer
+ Cretheus.Encode: value :: Value -> Encoding
Files
- CHANGELOG.md +6/−1
- cretheus.cabal +1/−1
- src/Cretheus/Decode.hs +1/−0
- src/Cretheus/Encode.hs +3/−0
- src/Cretheus/Internal/Decode.hs +34/−2
- src/Cretheus/Internal/Encode.hs +41/−22
CHANGELOG.md view
@@ -1,3 +1,8 @@-## [0.1.0] - Unreleased+## [1.1.0] – October 24, 2025++- Add `Cretheus.Decode.integer`+- Add `Cretheus.Encode.value`++## [1.0.0] – October 24, 2025 - Initial release.
cretheus.cabal view
@@ -13,7 +13,7 @@ stability: experimental synopsis: A clean aeson wrapper tested-with: GHC == 9.8.4, GHC == 9.10.1, GHC == 9.12.2-version: 1.0.0+version: 1.1.0 extra-source-files: CHANGELOG.md
src/Cretheus/Decode.hs view
@@ -15,6 +15,7 @@ int, int32, int64,+ integer, float, double,
src/Cretheus/Encode.hs view
@@ -39,6 +39,9 @@ -- ** Null encoders null,++ -- ** Value encoders+ value, ) where
src/Cretheus/Internal/Decode.hs view
@@ -3,15 +3,16 @@ ObjectDecoder, array, bool,- fromBytes,- fromLazyBytes, double, float,+ fromBytes,+ fromLazyBytes, fromText, fromValue, int, int32, int64,+ integer, keyMap, list, map,@@ -97,6 +98,7 @@ case Aeson.eitherDecodeStrict bytes of Left err -> Left (Text.pack err) Right (D result :: D s a) -> Right result+{-# INLINEABLE fromBytes #-} -- | Decode lazy bytes. fromLazyBytes :: Decoder a -> Lazy.ByteString -> Either Text a@@ -105,11 +107,13 @@ case Aeson.eitherDecode bytes of Left err -> Left (Text.pack err) Right (D result :: D s a) -> Right result+{-# INLINEABLE fromLazyBytes #-} -- | Decode text. fromText :: Decoder a -> Text -> Either Text a fromText decoder str = fromBytes decoder (Text.encodeUtf8 str)+{-# INLINEABLE fromText #-} -- | Decode a value. fromValue :: Decoder a -> Aeson.Value -> Either Text a@@ -117,96 +121,121 @@ case Aeson.parseEither decoder val of Left err -> Left (Text.pack err) Right result -> Right result+{-# INLINEABLE fromValue #-} -- | A value decoder. value :: Decoder Aeson.Value value = Decoder Aeson.parseJSON+{-# INLINEABLE value #-} -- | A bool decoder. bool :: Decoder Bool bool = Decoder Aeson.parseJSON+{-# INLINEABLE bool #-} -- | An int decoder. int :: Decoder Int int = Decoder Aeson.parseJSON+{-# INLINEABLE int #-} -- | A 32-bit int decoder. int32 :: Decoder Int32 int32 = Decoder Aeson.parseJSON+{-# INLINEABLE int32 #-} -- | A 64-bit int decoder. int64 :: Decoder Int64 int64 = Decoder Aeson.parseJSON+{-# INLINEABLE int64 #-} +-- | An integer decoder.+integer :: Decoder Integer+integer =+ Decoder Aeson.parseJSON+{-# INLINEABLE integer #-}+ -- | A 32-bit float decoder. float :: Decoder Float float = Decoder Aeson.parseJSON+{-# INLINEABLE float #-} -- | A 64-bit float decoder. double :: Decoder Double double = Decoder Aeson.parseJSON+{-# INLINEABLE double #-} -- | A text decoder. text :: Decoder Text text = Decoder Aeson.parseJSON+{-# INLINEABLE text #-} -- | A timestamp decoder (ISO 8601). utcTime :: Decoder UTCTime utcTime = Decoder Aeson.parseJSON+{-# INLINEABLE utcTime #-} -- | A list decoder. list :: Decoder a -> Decoder [a] list = fmap Vector.toList . vector+{-# INLINEABLE list #-} -- | An array decoder. array :: Decoder a -> Decoder (Array a) array (Decoder f) = Decoder (Aeson.withArray "" (traverse f . Vector.toArray))+{-# INLINEABLE array #-} -- | A vector decoder. vector :: Decoder a -> Decoder (Vector a) vector (Decoder f) = Decoder (Aeson.withArray "" (traverse f))+{-# INLINEABLE vector #-} -- | A set decoder. set :: (Ord a) => Decoder a -> Decoder (Set a) set = fmap Set.fromList . list+{-# INLINEABLE set #-} -- | An object decoder. object :: ObjectDecoder a -> Decoder a object (ObjectDecoder f) = Decoder (Aeson.withObject "" f)+{-# INLINEABLE object #-} -- | An object property decoder. property :: Aeson.Key -> Decoder a -> ObjectDecoder a property k (Decoder f) = ObjectDecoder \o -> Aeson.explicitParseField f o k+{-# INLINEABLE property #-} -- | An optional object property decoder. optionalProperty :: Aeson.Key -> Decoder a -> ObjectDecoder (Maybe a) optionalProperty k (Decoder f) = ObjectDecoder \o -> Aeson.explicitParseFieldMaybe' f o k+{-# INLINEABLE optionalProperty #-} -- | A map decoder. map :: (Ord k) => (Aeson.Key -> k) -> Decoder a -> Decoder (Map k a) map fromKey (Decoder f) = object (ObjectDecoder (Aeson.KeyMap.foldrWithKey (\k v -> liftA2 (Map.insert (fromKey k)) (f v)) (pure Map.empty)))+{-# INLINEABLE map #-} -- | A key map decoder. keyMap :: Decoder a -> Decoder (Aeson.KeyMap a) keyMap (Decoder f) = object (ObjectDecoder (Aeson.KeyMap.traverse f))+{-# INLINEABLE keyMap #-} -- | A null decoder. null :: Decoder ()@@ -214,6 +243,7 @@ Decoder \case Aeson.Null -> pure () _ -> fail "expected null"+{-# INLINEABLE null #-} -- | A nullable decoder. nullable :: Decoder v -> Decoder (Maybe v)@@ -221,6 +251,7 @@ Decoder \case Aeson.Null -> pure Nothing val -> Just <$> f val+{-# INLINEABLE nullable #-} -- | Refine a decoder with a predicate. refine :: (a -> Either Text b) -> Decoder a -> Decoder b@@ -230,3 +261,4 @@ case p x of Left err -> fail (Text.unpack err) Right y -> pure y+{-# INLINEABLE refine #-}
src/Cretheus/Internal/Encode.hs view
@@ -23,6 +23,7 @@ set, text, utcTime,+ value, vector, ) where@@ -67,100 +68,115 @@ asBytes :: Encoding -> ByteString asBytes = ByteString.Lazy.toStrict . asLazyBytes+{-# INLINEABLE asBytes #-} -- | Interpret an encoding as bytes. asLazyBytes :: Encoding -> LazyByteString asLazyBytes = Aeson.encodingToLazyByteString . asAesonEncoding+{-# INLINEABLE asLazyBytes #-} -- | Interpret an encoding as a bytes builder. asBytesBuilder :: Encoding -> ByteString.Builder asBytesBuilder = Aeson.fromEncoding . asAesonEncoding+{-# INLINEABLE asBytesBuilder #-} -- | Interpret an encoding as text. asText :: Encoding -> Text asText = Text.decodeUtf8 . asBytes+{-# INLINEABLE asText #-} -- | Interpret an encoding as a value. asValue :: Encoding -> Aeson.Value-asValue (Encoding _ value) =- value+asValue (Encoding _ val) =+ val+{-# INLINEABLE asValue #-} +-- | A value encoder.+value :: Aeson.Value -> Encoding+value val =+ Encoding (Aeson.value val) val+{-# INLINEABLE value #-}+ -- | A bool encoder. bool :: Bool -> Encoding bool = mk Aeson.bool Aeson.toJSON+{-# INLINEABLE bool #-} -- | An int encoder. int :: Int -> Encoding int = int64 . fromIntegral @Int @Int64+{-# INLINEABLE int #-} -- | A 32-bit int encoder. int32 :: Int32 -> Encoding int32 = mk Aeson.int32 Aeson.toJSON+{-# INLINEABLE int32 #-} -- | A 64-bit int encoder. int64 :: Int64 -> Encoding int64 = mk Aeson.int64 Aeson.toJSON+{-# INLINEABLE int64 #-} -- | A 32-bit float encoder. float :: Float -> Encoding float = mk Aeson.float Aeson.toJSON+{-# INLINEABLE float #-} -- | A 32-bit float encoder. double :: Double -> Encoding double = mk Aeson.double Aeson.toJSON+{-# INLINEABLE double #-} -- | A text encoder. text :: Text -> Encoding text = mk Aeson.text Aeson.toJSON+{-# INLINEABLE text #-} -- | A timestamp encoder (ISO 8601). utcTime :: UTCTime -> Encoding utcTime = mk Aeson.utcTime Aeson.toJSON+{-# INLINEABLE utcTime #-} -- | A null encoder. null :: Encoding null = Encoding Aeson.null_ Aeson.Null+{-# INLINEABLE null #-} -- | A list encoder. list :: (a -> Encoding) -> [a] -> Encoding list f =- mk toAesonEncoding toAesonValue- where- toAesonEncoding = Aeson.list (asAesonEncoding . f)- toAesonValue = Aeson.toJSON . List.map (asValue . f)+ mk (Aeson.list (asAesonEncoding . f)) (Aeson.toJSON . List.map (asValue . f))+{-# INLINEABLE list #-} -- | An array encoder. array :: (a -> Encoding) -> Array a -> Encoding array f =- mk toAesonEncoding toAesonValue- where- toAesonEncoding = Aeson.list (asAesonEncoding . f) . Foldable.toList @Array- toAesonValue = Aeson.Array . Vector.fromArray . fmap @Array (asValue . f)+ mk (Aeson.list (asAesonEncoding . f) . Foldable.toList @Array) (Aeson.Array . Vector.fromArray . fmap @Array (asValue . f))+{-# INLINEABLE array #-} -- | A vector encoder. vector :: (a -> Encoding) -> Vector a -> Encoding vector f =- mk toAesonEncoding toAesonValue- where- toAesonEncoding = Aeson.list (asAesonEncoding . f) . Vector.toList- toAesonValue = Aeson.Array . Vector.map (asValue . f)+ mk (Aeson.list (asAesonEncoding . f) . Vector.toList) (Aeson.Array . Vector.map (asValue . f))+{-# INLINEABLE vector #-} -- | A set encoder. set :: (a -> Encoding) -> Set a -> Encoding set f = list f . Set.toList+{-# INLINEABLE set #-} -- | An object property encoding. data PropertyEncoding@@ -195,30 +211,33 @@ object :: [PropertyEncoding] -> Encoding object = mk propsToAesonEncoding propsToAesonValue . foldr addProperty []+{-# INLINEABLE object #-} -- | An object property encoder. property :: Aeson.Key -> Encoding -> PropertyEncoding property key val = Algo (Prop key val)+{-# INLINEABLE property #-} -- | A optional object property encoder. optionalProperty :: Aeson.Key -> Maybe Encoding -> PropertyEncoding optionalProperty key = \case Nothing -> Nada Just val -> Algo (Prop key val)+{-# INLINEABLE optionalProperty #-} -- | A map encoder. map :: (k -> Aeson.Key) -> (a -> Encoding) -> Map k a -> Encoding map f g =- mk toAesonEncoding toAesonValue- where- toAesonEncoding = Aeson.dict (Aeson.text . Aeson.Key.toText . f) (asAesonEncoding . g) Map.foldrWithKey- toAesonValue = Aeson.Object . Aeson.KeyMap.fromList . List.map (\(k, v) -> (f k, asValue (g v))) . Map.toList+ mk+ (Aeson.dict (Aeson.text . Aeson.Key.toText . f) (asAesonEncoding . g) Map.foldrWithKey)+ (Aeson.Object . Aeson.KeyMap.fromList . List.map (\(k, v) -> (f k, asValue (g v))) . Map.toList)+{-# INLINEABLE map #-} -- | A key map encoder. keyMap :: (a -> Encoding) -> Aeson.KeyMap a -> Encoding keyMap f =- mk toAesonEncoding toAesonValue- where- toAesonEncoding = Aeson.dict (Aeson.text . Aeson.Key.toText) (asAesonEncoding . f) Aeson.KeyMap.foldrWithKey- toAesonValue = Aeson.Object . Aeson.KeyMap.map (asValue . f)+ mk+ (Aeson.dict (Aeson.text . Aeson.Key.toText) (asAesonEncoding . f) Aeson.KeyMap.foldrWithKey)+ (Aeson.Object . Aeson.KeyMap.map (asValue . f))+{-# INLINEABLE keyMap #-}