diff --git a/CHANGELOG.md b/CHANGELOG.md index ff53874c..c6f5b807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ The changelog is available [on GitHub][2]. Export a function for parsing TOML keys. * [#311](https://github.com/kowainik/tomland/issues/311): Reimplement custom `TomlState` instead of using `MaybeT` and `State`. +* [#272](https://github.com/kowainik/tomland/issues/272): + Add `TomlTable` newtype to be used in generic `DerivingVia`. ## 1.2.1.0 — Nov 6, 2019 diff --git a/examples/Main.hs b/examples/Main.hs index 66122e13..ee7c1cdb 100644 --- a/examples/Main.hs +++ b/examples/Main.hs @@ -1,5 +1,7 @@ {-# OPTIONS -Wno-unused-top-binds #-} + {-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DerivingVia #-} module Main (main) where @@ -7,6 +9,7 @@ import Control.Applicative ((<|>)) import Control.Arrow ((>>>)) import Data.Hashable (Hashable) import Data.HashSet (HashSet) +import Data.ByteString (ByteString) import Data.IntSet (IntSet) import Data.List.NonEmpty (NonEmpty) import Data.Map.Strict (Map) @@ -18,6 +21,7 @@ import GHC.Generics (Generic) import Toml (TomlCodec, TomlParseError (..), pretty, (.=), ()) import Toml.Type (TOML (..), Value (..)) import Toml.Type.Edsl (mkToml, table, (=:)) +import Toml.Codec.Generic (TomlTable (..), stripTypeNameCodec, HasCodec (..), ByteStringAsBytes (..)) import qualified Data.Text.IO as TIO @@ -177,6 +181,24 @@ testT = Test Toml.match (Toml._Right >>> Toml._Double) ) "either" +data GenericPerson = GenericPerson + { genericPersonName :: !Text + , genericPersonAddress :: !Address + } deriving stock (Generic) + +data Address = Address + { addressStreet :: !Text + , addressHouse :: !Int + } deriving stock (Generic) + deriving HasCodec via (TomlTable Address) + +testGeneric :: TomlCodec GenericPerson +testGeneric = stripTypeNameCodec + +newtype MyByteString = MyByteString + { unMyByteString :: ByteString + } deriving HasCodec via ByteStringAsBytes + main :: IO () main = do TIO.putStrLn "=== Printing manually specified TOML ===" @@ -194,6 +216,12 @@ main = do Left msgs -> Toml.prettyTomlDecodeErrors msgs Right test -> Toml.encode testT test + TIO.putStrLn "=== Testing Deriving Via ===" + genericFile <- TIO.readFile "examples/generic.toml" + TIO.putStrLn $ case Toml.decode testGeneric genericFile of + Left msg -> Toml.prettyTomlDecodeErrors msg + Right test -> Toml.encode testGeneric test + myToml :: TOML myToml = mkToml $ do "a" =: Bool True diff --git a/examples/generic.toml b/examples/generic.toml new file mode 100644 index 00000000..16688de2 --- /dev/null +++ b/examples/generic.toml @@ -0,0 +1,5 @@ +name = "foo" + +[address] + addressStreet = "Bar" + addressHouse = 42 diff --git a/src/Toml/Codec/Generic.hs b/src/Toml/Codec/Generic.hs index 658eceb4..b92fc907 100644 --- a/src/Toml/Codec/Generic.hs +++ b/src/Toml/Codec/Generic.hs @@ -125,6 +125,9 @@ module Toml.Codec.Generic , ByteStringAsBytes (..) , LByteStringAsText (..) , LByteStringAsBytes (..) + + -- * Deriving Via + , TomlTable (..) ) where import Data.ByteString (ByteString) @@ -669,10 +672,6 @@ instance HasCodec a => HasCodec (Last a) where hasCodec = Toml.last (hasCodec @a) {-# INLINE hasCodec #-} -{- -TODO: uncomment when higher-kinded roles will be implemented -* https://github.com/ghc-proposals/ghc-proposals/pull/233 - {- | @newtype@ for generic deriving of 'HasCodec' typeclass for custom data types that should we wrapped into separate table. Use it only for data types that are fields of another data types. @@ -712,7 +711,6 @@ instance (Generic a, GenericCodec (Rep a)) => HasCodec (TomlTable a) where instance (Generic a, GenericCodec (Rep a)) => HasItemCodec (TomlTable a) where hasItemCodec = Right $ Toml.diwrap $ genericCodec @a --} {- $bytestring There are two ways to encode 'ByteString' in TOML: @@ -726,9 +724,7 @@ To handle all these cases, @tomland@ provides helpful newtypes, specifically: * 'ByteStringAsBytes' * 'LByteStringAsText' * 'LByteStringAsBytes' --} -{- TODO: uncomment when the same GHC issue as above is resolved: As a bonus, on GHC >= 8.6 you can use these newtypes with the @DerivingVia@ extensions for your own 'ByteString' types. diff --git a/tomland.cabal b/tomland.cabal index fbc41d5b..c90b0f4f 100644 --- a/tomland.cabal +++ b/tomland.cabal @@ -142,8 +142,12 @@ executable readme executable play-tomland import: common-options + -- We are using DerivingVia that works only with > 8.6 + if impl(ghc < 8.6) + buildable: False main-is: Main.hs build-depends: tomland + , bytestring , containers , hashable , text