{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- | Support for RSS extensions.
-- Cf specification at .
--
-- For now, only parsing is implemented. Rendering will be implemented later.
module Text.RSS.Extensions where
-- {{{ Imports
import Control.Exception.Safe as Exception
import Data.Conduit
import Data.Maybe
import Data.Proxy
import Data.Singletons
import Data.Singletons.Prelude.Bool
import Data.Singletons.Prelude.Eq
import Data.Singletons.Prelude.List
import Data.Text
import Data.Vinyl.Core
import Data.Vinyl.TypeLevel
import Data.XML.Types
import Debug.Trace
import GHC.Generics
import Text.Atom.Conduit.Parse
import Text.Atom.Types
import Text.Read (readMaybe)
import Text.RSS.Types
import Text.XML.Stream.Parse
import URI.ByteString
-- }}}
-- | Class of RSS extensions that can be parsed.
class ParseRssExtension a where
-- | This parser will be fed with all 'Event's within the @\@ element.
-- Therefore, it is expected to ignore 'Event's unrelated to the RSS extension.
parseRssChannelExtension :: MonadThrow m => ConduitM Event o m (RssChannelExtension a)
-- | This parser will be fed with all 'Event's within the @\- @ element.
-- Therefore, it is expected to ignore 'Event's unrelated to the RSS extension.
parseRssItemExtension :: MonadThrow m => ConduitM Event o m (RssItemExtension a)
-- | Requirement on a list of extension tags to be able to parse and combine them.
type ParseRssExtensions (e :: [*]) = (AllConstrained ParseRssExtension e, SingI e)
-- | Parse a combination of RSS extensions at @\@ level.
parseRssChannelExtensions :: ParseRssExtensions e => MonadThrow m => ConduitM Event o m (RssChannelExtensions e)
parseRssChannelExtensions = f sing where
f :: AllConstrained ParseRssExtension e => MonadThrow m
=> Sing e -> ConduitM Event o m (RssChannelExtensions e)
f SNil = return $ RssChannelExtensions RNil
f (SCons _ es) = fmap RssChannelExtensions $ getZipConduit $ (:&)
<$> ZipConduit parseRssChannelExtension
<*> ZipConduit (rssChannelExtension <$> f es)
-- | Parse a combination of RSS extensions at @\
- @ level.
parseRssItemExtensions :: ParseRssExtensions e => MonadThrow m => ConduitM Event o m (RssItemExtensions e)
parseRssItemExtensions = f sing where
f :: AllConstrained ParseRssExtension e => MonadThrow m
=> Sing e -> ConduitM Event o m (RssItemExtensions e)
f SNil = return $ RssItemExtensions RNil
f (SCons _ es) = fmap RssItemExtensions $ getZipConduit $ (:&)
<$> ZipConduit parseRssItemExtension
<*> ZipConduit (rssItemExtension <$> f es)