content: {-# LANGUAGE
      DataKinds
    , RankNTypes
    , ScopedTypeVariables
    , TypeFamilies
    #-}
  -- | Combinators for specifying the input/output dictionaries of a
  -- 'Handler'. The combinators can be combined using @(@'.'@)@.
  module Rest.Dictionary.Combinators
    (
    -- ** Input dictionaries
  
      stringI
    , xmlTextI
    , fileI
    , readI
    , xmlI
    , rawXmlI
    , jsonI
    , rawJsonI
    , rawJsonAndXmlI
  
    -- ** Output dictionaries
  
    , stringO
    , fileO
    , xmlO
    , rawXmlO
    , jsonO
    , rawJsonO
    , rawJsonAndXmlO
    , multipartO
  
    -- ** Error dictionaries
  
    , jsonE
    , xmlE
  
    -- ** Composed dictionaries
  
    , xmlJsonI
    , xmlJsonO
    , xmlJsonE
    , xmlJson
  
    -- ** Header dictionaries
  
    , mkHeader
    , addHeader
  
    -- ** Parameter dictionaries
  
    , mkPar
    , addPar
  
    -- ** Deprecated
  
    , someI
    , someO
    , someE
    ) where
  
  import Prelude hiding (id, (.))
  
  import Control.Category
  import Data.Aeson
  import Data.ByteString.Lazy (ByteString)
  import Data.JSON.Schema
  import Data.Text.Lazy (Text)
  import Data.Typeable
  import Network.Multipart (BodyPart)
  import Text.XML.HXT.Arrow.Pickle
  import qualified Data.Label.Total as L
  
  import Rest.Dictionary.Types
  import Rest.Info
  import Rest.Types.Error
  
  -- | Set custom sub-dictionary for recognizing headers.
  
  mkHeader :: Header h -> Dict x p i o e -> Dict h p i o e
  mkHeader = L.set headers
  
  -- | Add custom sub-dictionary for recognizing headers.
  
  addHeader :: Header h -> Dict h' p i o e -> Dict (h, h') p i o e
  addHeader = L.modify headers . TwoHeaders
  
  -- | Set custom sub-dictionary for recognizing parameters.
  
  mkPar :: Param p -> Dict h x i o e -> Dict h p i o e
  mkPar = L.set params
  
  -- | Add custom sub-dictionary for recognizing parameters.
  
  addPar :: Param p -> Dict h p' i o e -> Dict h (p, p') i o e
  addPar = L.modify params . TwoParams
  
  -- | Open up input type for extension with custom dictionaries.
  
  {-# DEPRECATED someI "This can be safely removed, it is now just the identity." #-}
  someI :: Dict h p i o e -> Dict h p i o e
  someI = id
  
  -- | Allow direct usage of as input as `String`.
  
  stringI :: Dict h p 'Nothing o e -> Dict h p ('Just String) o e
  stringI = L.set inputs (Dicts [StringI])
  
  -- | Allow direct usage of as input as raw Xml `Text`.
  
  xmlTextI :: Dict h p 'Nothing o e -> Dict h p ('Just Text) o e
  xmlTextI = L.set inputs (Dicts [XmlTextI])
  
  -- | Allow usage of input as file contents, represented as a `ByteString`.
  
  fileI :: Dict h p 'Nothing o e -> Dict h p ('Just ByteString) o e
  fileI = L.set inputs (Dicts [FileI])
  
  -- | The input can be read into some instance of `Read`. For inspection reasons
  -- the type must also be an instance of both `Info` and `Show`.
  
  readI :: (Info i, Read i, Show i, FromMaybe i i' ~ i) => Dict h p i' o e -> Dict h p ('Just i) o e
  readI = L.modify inputs (modDicts (ReadI:))
  
  -- | The input can be read into some instance of `XmlPickler`.
  
  xmlI :: (Typeable i, XmlPickler i, FromMaybe i i' ~ i) => Dict h p i' o e -> Dict h p ('Just i) o e
  xmlI = L.modify inputs (modDicts (XmlI:))
  
  -- | The input can be used as an XML `ByteString`.
  
  rawXmlI :: Dict h p 'Nothing o e -> Dict h p ('Just ByteString) o e
  rawXmlI = L.set inputs (Dicts [RawXmlI])
  
  -- | The input can be used as a JSON `ByteString`.
  
  rawJsonI :: Dict h p 'Nothing o e -> Dict h p ('Just ByteString) o e
  rawJsonI = L.set inputs (Dicts [RawJsonI])
  
  -- | The input can be read into some instance of `Json`.
  
  jsonI :: (Typeable i, FromJSON i, JSONSchema i, FromMaybe i i' ~ i) => Dict h p i' o e -> Dict h p ('Just i) o e
  jsonI = L.modify inputs (modDicts (JsonI:))
  
  -- | The input can be used as a JSON or XML `ByteString`.
  --
  -- An API client can send either format so the handler needs to handle both.
  
  rawJsonAndXmlI :: Dict h p 'Nothing o e -> Dict h p ('Just (Either Json Xml)) o e
  rawJsonAndXmlI = L.set inputs (Dicts [RawJsonAndXmlI])
  
  -- | Open up output type for extension with custom dictionaries.
  
  {-# DEPRECATED someO "This can be safely removed, it is now just the identity." #-}
  someO :: Dict h p i o e -> Dict h p i o e
  someO = id
  
  -- | Allow output as plain String.
  
  stringO :: Dict h p i 'Nothing e -> Dict h p i ('Just String) e
  stringO = L.set outputs (Dicts [StringO])
  
  -- | Allow file output using a combination of the raw data, the file
  -- name, and an attachment flag (causing the file to be downloaded by
  -- browsers instead of shown). The mime type will be determined from
  -- the file extension by your web server library, or
  -- "application/octet-stream" with an unknown extension.
  
  fileO :: Dict h p i 'Nothing e -> Dict h p i ('Just (ByteString, String, Bool)) e
  fileO = L.set outputs (Dicts [FileO])
  
  -- | Allow output as XML using the `XmlPickler` type class.
  
  xmlO :: (Typeable o, XmlPickler o, FromMaybe o o' ~ o) => Dict h p i o' e -> Dict h p i ('Just o) e
  xmlO = L.modify outputs (modDicts (XmlO:))
  
  -- | Allow output as raw XML represented as a `ByteString`.
  
  rawXmlO :: Dict h p i 'Nothing e -> Dict h p i ('Just ByteString) e
  rawXmlO = L.set outputs (Dicts [RawXmlO])
  
  -- | Allow output as raw JSON represented as a `ByteString`.
  
  rawJsonO :: Dict h p i 'Nothing e -> Dict h p i ('Just ByteString) e
  rawJsonO = L.set outputs (Dicts [RawJsonO])
  
  -- | Allow output as JSON using the `Json` type class.
  
  jsonO :: (Typeable o, ToJSON o, JSONSchema o, FromMaybe o o' ~ o) => Dict h p i o' e -> Dict h p i ('Just o) e
  jsonO = L.modify outputs (modDicts (JsonO:))
  
  -- | Allow output as raw JSON and XML represented as `ByteString`s.
  -- Both values are needed since the accept header determines which one
  -- to send.
  
  rawJsonAndXmlO :: Dict h p i 'Nothing e -> Dict h p i ('Just ByteString) e
  rawJsonAndXmlO = L.set outputs (Dicts [RawJsonAndXmlO])
  
  -- | Allow output as multipart. Writes out the ByteStrings separated
  -- by boundaries, with content type 'multipart/mixed'.
  
  multipartO :: Dict h p i 'Nothing e -> Dict h p i ('Just [BodyPart]) e
  multipartO = L.set outputs (Dicts [MultipartO])
  
  -- | Open up error type for extension with custom dictionaries.
  
  {-# DEPRECATED someE "This can be safely removed, it is now just the identity." #-}
  someE :: Dict h p i o e -> Dict h p i o e
  someE = id
  
  -- | Allow error output as JSON using the `Json` type class.
  
  jsonE :: (ToResponseCode e, Typeable e, ToJSON e, JSONSchema e, FromMaybe e e' ~ e) => Dict h p i o e' -> Dict h p i o ('Just e)
  jsonE = L.modify errors (modDicts (JsonE:))
  
  -- | Allow error output as XML using the `XmlPickler` type class.
  
  xmlE :: (ToResponseCode e, Typeable e, XmlPickler e, FromMaybe e e' ~ e) => Dict h p i o e' -> Dict h p i o ('Just e)
  xmlE = L.modify errors (modDicts (XmlE:))
  
  -- | The input can be read into some instance of both `Json` and `XmlPickler`.
  
  xmlJsonI :: (Typeable i, FromJSON i, JSONSchema i, XmlPickler i, FromMaybe i i' ~ i) => Dict h p i' o e -> Dict h p ('Just i) o e
  xmlJsonI = xmlI . jsonI
  
  -- | Allow output as JSON using the `Json` type class and allow output as XML
  -- using the `XmlPickler` type class.
  
  xmlJsonO :: (Typeable o, ToJSON o, JSONSchema o, XmlPickler o, FromMaybe o o' ~ o) => Dict h p i o' e -> Dict h p i ('Just o) e
  xmlJsonO = xmlO . jsonO
  
  -- | Allow error output as JSON using the `Json` type class and allow output as
  -- XML using the `XmlPickler` type class.
  
  xmlJsonE :: (ToResponseCode e, Typeable e, ToJSON e, JSONSchema e, XmlPickler e, FromMaybe e e' ~ e) => Dict h p i o e' -> Dict h p i o ('Just e)
  xmlJsonE = xmlE . jsonE
  
  -- | The input can be read into some instance of both `Json` and `XmlPickler`
  -- and allow output as JSON using the `Json` type class and allow output as XML
  -- using the `XmlPickler` type class.
  
  xmlJson :: ( Typeable i, FromJSON i, JSONSchema i, XmlPickler i
             , Typeable o, ToJSON o, JSONSchema o, XmlPickler o
             , FromMaybe i i' ~ i, FromMaybe o o' ~ o
             )
          => Dict h p i' o' e -> Dict h p ('Just i) ('Just o) e
  xmlJson = xmlJsonI . xmlJsonO
  