autodocodec 0.6.0.0 → 0.7.0.0
raw patch · 4 files changed
+39/−18 lines, 4 filessetup-changedPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Autodocodec.Codec: Result :: Either String a -> Result a
- Autodocodec.Codec: [runResult] :: Result a -> Either String a
- Autodocodec.Codec: instance Control.Monad.Fail.MonadFail Autodocodec.Codec.Result
- Autodocodec.Codec: instance GHC.Base.Applicative Autodocodec.Codec.Result
- Autodocodec.Codec: instance GHC.Base.Functor Autodocodec.Codec.Result
- Autodocodec.Codec: instance GHC.Base.Monad Autodocodec.Codec.Result
- Autodocodec.Codec: newtype Result a
Files
- CHANGELOG.md +19/−0
- Setup.hs +2/−0
- autodocodec.cabal +3/−2
- src/Autodocodec/Codec.hs +15/−16
CHANGELOG.md view
@@ -1,5 +1,24 @@ # Changelog +## [0.7.0.0] - 2026-10-07++### Fixed++* `optionalFieldOrNullWithOmittedDefault`, `optionalFieldOrNullWithOmittedDefault'`,+ `optionalFieldOrNullWithOmittedDefaultWith` and+ `optionalFieldOrNullWithOmittedDefaultWith'` now omit the key when the value+ is the default value, as they document, instead of encoding `null`.+ Both encodings parse back to the default value, so this changes the output+ rather than what can be read.++* `unsafeUnboundedNaturalCodec` no longer throws an arithmetic underflow when+ it is given a negative number. It fails to parse instead.++### Removed++* The `Result` newtype and its instances.+ Nothing used it: it was left over from the time codecs it was written for.+ ## [0.6.0.0] - 2026-07-14 This is technically a breaking change but it's unlikely that you'll need to
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
autodocodec.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: autodocodec-version: 0.6.0.0+version: 0.7.0.0 synopsis: Self-documenting encoder and decoder homepage: https://github.com/NorfairKing/autodocodec#readme bug-reports: https://github.com/NorfairKing/autodocodec/issues@@ -37,6 +37,7 @@ Paths_autodocodec hs-source-dirs: src+ ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wpartial-fields -Widentities -Wredundant-constraints -Wcpp-undef build-depends: aeson , base >=4.7 && <5@@ -61,7 +62,7 @@ Paths_autodocodec hs-source-dirs: doctest/- ghc-options: -main-is DocTest -threaded -rtsopts -with-rtsopts=-N -Wall+ ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wpartial-fields -Widentities -Wredundant-constraints -Wcpp-undef -main-is DocTest -threaded -rtsopts -with-rtsopts=-N -Wall build-depends: base >=4.7 && <5 , doctest
src/Autodocodec/Codec.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RankNTypes #-}@@ -1178,7 +1177,11 @@ f = \case Just v -> v Nothing -> defaultValue- g v = if v == defaultValue then Nothing else Just v+ -- Not 'if v == defaultValue then Nothing else Just v': the underlying+ -- codec omits the key when what it is given equals its own default, which+ -- is 'Just defaultValue', so answering 'Nothing' for the default value is+ -- what would write @null@ instead of omitting the key.+ g = Just -- | Like 'optionalFieldWithOmittedDefaultWith'', but the value may also be -- @null@ and that will be interpreted as the default value.@@ -1193,10 +1196,11 @@ ObjectCodec output output optionalFieldOrNullWithOmittedDefaultWith' key c defaultValue = dimapCodec f g $ optionalFieldWithOmittedDefaultWith' key (maybeCodec c) (Just defaultValue) where+ -- See the note on 'optionalFieldOrNullWithOmittedDefaultWith'. f = \case Just v -> v Nothing -> defaultValue- g v = if v == defaultValue then Nothing else Just v+ g = Just -- | An optional, or null, field --@@ -1630,8 +1634,14 @@ unsafeUnboundedNaturalCodec = bimapCodec go fromIntegral scientificCodec where- go s = case Scientific.floatingOrInteger s :: Either Float Natural of- Right i -> Right i+ -- Via 'Integer' rather than straight to 'Natural': 'floatingOrInteger'+ -- reaches its result type through 'fromInteger', and 'fromInteger' into+ -- 'Natural' throws on a negative number, so asking it for a 'Natural'+ -- turns a number this codec should refuse into an arithmetic underflow.+ go s = case Scientific.floatingOrInteger s :: Either Float Integer of+ Right i+ | i < 0 -> Left ("Number is negative: " <> show s)+ | otherwise -> Right (fromInteger i) Left _ -> Left ("Number is not an integer: " <> show s) -- | A codec for a literal piece of 'Text'.@@ -2078,17 +2088,6 @@ Text -> JSONCodec a codecViaAeson doc = bimapCodec (JSON.parseEither JSON.parseJSON) JSON.toJSON valueCodec <?> doc---- Could get this from https://hackage.haskell.org/package/either-result-0.3.1.0/docs/Control-Monad-Result.html#t:Result--- but just reimplementing here to avoid a dependency, as it's not exported anyway--- (well it is actually, until we give this module an explicit export list).--- We need to do this because `Either String a` doesn't have a `MonadFail` instance,--- but `Time.iso8601ParseM` expects it's return value to have a `MonadFail` instance.-newtype Result a = Result {runResult :: Either String a}- deriving newtype (Functor, Applicative, Monad)--instance MonadFail Result where- fail = Result . Left -- TODO 'aeson' has it's own custom datetime serialising code in the module @Data.Aeson.Encoding.Builder@: -- The core function here is `Data.Aeson.Encoding.Builder.timeOfDay64`.