Skip to content

Commit

Permalink
Fix input-output-hk#11: improve parsing
Browse files Browse the repository at this point in the history
co-authored by @andreabedini
  • Loading branch information
yvan-sraka committed Sep 22, 2023
1 parent cbd0c5d commit 1d536c1
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
38 changes: 37 additions & 1 deletion app/Foliage/Meta.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ where

import Control.Applicative ((<|>))
import Control.Monad (void)
import Control.Monad.State (modify)
import Data.HashMap.Strict qualified as HashMap
import Data.List (sortOn)
import Data.Maybe (fromMaybe)
import Data.Ord (Down (Down))
Expand Down Expand Up @@ -141,7 +143,7 @@ data PackageVersionSpec = PackageVersionSpec
sourceMetaCodec :: TomlCodec PackageVersionSpec
sourceMetaCodec =
PackageVersionSpec
<$> Toml.dioptional (timeCodec "timestamp")
<$> optionalTimeCodec "timestamp"
.= packageVersionTimestamp
<*> packageSourceCodec
.= packageVersionSource
Expand Down Expand Up @@ -204,3 +206,37 @@ withDefault :: (Eq a) => a -> TomlCodec a -> TomlCodec a
withDefault d c = (fromMaybe d <$> Toml.dioptional c) .= f
where
f a = if a == d then Nothing else Just a

-- | Codec for a maybe-missing time value.
--
-- Note this is different from dioptional timeCodec. With dioptional timeCodec,
-- if the user writes
-- timestamp = '2022-08-22T10:38:45Z'
-- rather then
-- timestamp = 2022-08-22T10:38:45Z
-- the timestamp will parse as Nothing because it won't match the zoneTime
-- type and it is not an error because it is optional.
--
-- We use a handrolled version of match (matchMaybe) to make it work.
--
-- See discussions at
-- 1. https://github.com/input-output-hk/foliage/issues/11
-- 2. https://github.com/input-output-hk/foliage/pull/57
-- 3. https://github.com/kowainik/tomland/issues/223
optionalTimeCodec :: Toml.Key -> TomlCodec (Maybe UTCTime)
optionalTimeCodec key =
Toml.dimap (fmap $ utcToZonedTime utc) (fmap zonedTimeToUTC) $ matchMaybe Toml._ZonedTime key

matchMaybe :: forall a. Toml.TomlBiMap a Toml.AnyValue -> Toml.Key -> TomlCodec (Maybe a)
matchMaybe bimap key = Toml.Codec input output
where
input :: Toml.TomlEnv (Maybe a)
input toml = case HashMap.lookup key (Toml.tomlPairs toml) of
Nothing -> pure Nothing
Just anyVal -> pure <$> Toml.whenLeftBiMapError key (Toml.backward bimap anyVal) pure

output :: Maybe a -> Toml.TomlState (Maybe a)
output Nothing = pure Nothing
output (Just a) = do
anyVal <- Toml.eitherToTomlState $ Toml.forward bimap a
Just a <$ modify (Toml.insertKeyAnyVal key anyVal)
2 changes: 2 additions & 0 deletions foliage.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ executable foliage
ed25519 >=0.0.5.0 && <0.1,
filepath >=1.4.2.1 && <1.5,
hackage-security >=0.6.2.1 && <0.7,
mtl,
network-uri >=2.6.4.1 && <2.7,
optparse-applicative >=0.17.0.0 && <0.18,
shake >=0.19.6 && <0.20,
Expand All @@ -66,6 +67,7 @@ executable foliage
time >=1.9.3 && <1.13,
time-compat >=1.9.6.1 && <1.10,
tomland >=1.3.3.1 && <1.4,
unordered-containers,
vector >=0.13.0.0 && <0.14,
with-utf8 >=1.0.2.3 && <1.1,
zlib >=0.6.2.3 && <0.7,
Expand Down

0 comments on commit 1d536c1

Please sign in to comment.