You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
6.8 KiB

-- Picklers and unpicklers convert Haskell data to XML and XML to Haskell data,
-- respectively. By convensions, pickler/unpickler ("PU") function names start
-- out with "xp".
{-# Language OverloadedStrings, ViewPatterns, NoMonomorphismRestriction #-}
{-# OPTIONS_HADDOCK hide #-}
module Network.Xmpp.Marshal where
import Data.XML.Pickle
import Data.XML.Types
import Network.Xmpp.Pickle
import Network.Xmpp.Types
xpStreamStanza :: PU [Node] (Either StreamErrorInfo Stanza)
xpStreamStanza = xpEither xpStreamError xpStanza
xpStanza :: PU [Node] Stanza
xpStanza = xpAlt stanzaSel
[ xpWrap IQRequestS (\(IQRequestS x) -> x) xpIQRequest
, xpWrap IQResultS (\(IQResultS x) -> x) xpIQResult
, xpWrap IQErrorS (\(IQErrorS x) -> x) xpIQError
, xpWrap MessageS (\(MessageS x) -> x) xpMessage
, xpWrap MessageErrorS (\(MessageErrorS x) -> x) xpMessageError
, xpWrap PresenceS (\(PresenceS x) -> x) xpPresence
, xpWrap PresenceErrorS (\(PresenceErrorS x) -> x) xpPresenceError
]
where
-- Selector for which pickler to execute above.
stanzaSel :: Stanza -> Int
stanzaSel (IQRequestS _) = 0
stanzaSel (IQResultS _) = 1
stanzaSel (IQErrorS _) = 2
stanzaSel (MessageS _) = 3
stanzaSel (MessageErrorS _) = 4
stanzaSel (PresenceS _) = 5
stanzaSel (PresenceErrorS _) = 6
xpMessage :: PU [Node] (Message)
xpMessage = xpWrap
(\((tp, qid, from, to, lang), ext) -> Message qid from to lang tp ext)
(\(Message qid from to lang tp ext) -> ((tp, qid, from, to, lang), ext))
(xpElem "{jabber:client}message"
(xp5Tuple
(xpDefault Normal $ xpAttr "type" xpPrim)
(xpAttrImplied "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
xpLangTag
-- TODO: NS?
)
(xpAll xpElemVerbatim)
)
xpPresence :: PU [Node] Presence
xpPresence = xpWrap
(\((qid, from, to, lang, tp), ext) -> Presence qid from to lang tp ext)
(\(Presence qid from to lang tp ext) -> ((qid, from, to, lang, tp), ext))
(xpElem "{jabber:client}presence"
(xp5Tuple
(xpAttrImplied "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
xpLangTag
(xpAttrImplied "type" xpPrim)
)
(xpAll xpElemVerbatim)
)
xpIQRequest :: PU [Node] IQRequest
xpIQRequest = xpWrap
(\((qid, from, to, lang, tp),body) -> IQRequest qid from to lang tp body)
(\(IQRequest qid from to lang tp body) -> ((qid, from, to, lang, tp), body))
(xpElem "{jabber:client}iq"
(xp5Tuple
(xpAttr "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
xpLangTag
((xpAttr "type" xpPrim))
)
xpElemVerbatim
)
14 years ago
xpIQResult :: PU [Node] IQResult
xpIQResult = xpWrap
(\((qid, from, to, lang, _tp),body) -> IQResult qid from to lang body)
(\(IQResult qid from to lang body) -> ((qid, from, to, lang, ()), body))
(xpElem "{jabber:client}iq"
(xp5Tuple
(xpAttr "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
xpLangTag
((xpAttrFixed "type" "result"))
)
(xpOption xpElemVerbatim)
)
----------------------------------------------------------
-- Errors
----------------------------------------------------------
xpErrorCondition :: PU [Node] StanzaErrorCondition
xpErrorCondition = xpWrap
(\(cond, (), ()) -> cond)
(\cond -> (cond, (), ()))
(xpElemByNamespace
"urn:ietf:params:xml:ns:xmpp-stanzas"
xpPrim
xpUnit
xpUnit
)
xpStanzaError :: PU [Node] StanzaError
xpStanzaError = xpWrap
(\(tp, (cond, txt, ext)) -> StanzaError tp cond txt ext)
(\(StanzaError tp cond txt ext) -> (tp, (cond, txt, ext)))
(xpElem "{jabber:client}error"
(xpAttr "type" xpPrim)
(xp3Tuple
xpErrorCondition
(xpOption $ xpElem "{jabber:client}text"
(xpAttrImplied xmlLang xpPrim)
(xpContent xpId)
)
(xpOption xpElemVerbatim)
)
)
xpMessageError :: PU [Node] (MessageError)
xpMessageError = xpWrap
(\((_, qid, from, to, lang), (err, ext)) ->
MessageError qid from to lang err ext)
(\(MessageError qid from to lang err ext) ->
(((), qid, from, to, lang), (err, ext)))
(xpElem "{jabber:client}message"
(xp5Tuple
(xpAttrFixed "type" "error")
(xpAttrImplied "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
(xpAttrImplied xmlLang xpPrim)
-- TODO: NS?
)
(xp2Tuple xpStanzaError (xpAll xpElemVerbatim))
)
xpPresenceError :: PU [Node] PresenceError
xpPresenceError = xpWrap
(\((qid, from, to, lang, _),(err, ext)) ->
PresenceError qid from to lang err ext)
(\(PresenceError qid from to lang err ext) ->
((qid, from, to, lang, ()), (err, ext)))
(xpElem "{jabber:client}presence"
(xp5Tuple
(xpAttrImplied "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
xpLangTag
(xpAttrFixed "type" "error")
)
(xp2Tuple xpStanzaError (xpAll xpElemVerbatim))
)
xpIQError :: PU [Node] IQError
xpIQError = xpWrap
(\((qid, from, to, lang, _tp),(err, body)) ->
IQError qid from to lang err body)
(\(IQError qid from to lang err body) ->
((qid, from, to, lang, ()), (err, body)))
(xpElem "{jabber:client}iq"
(xp5Tuple
(xpAttr "id" xpPrim)
(xpAttrImplied "from" xpPrim)
(xpAttrImplied "to" xpPrim)
xpLangTag
((xpAttrFixed "type" "error"))
)
(xp2Tuple xpStanzaError (xpOption xpElemVerbatim))
)
xpStreamError :: PU [Node] StreamErrorInfo
xpStreamError = xpWrap
(\((cond,() ,()), txt, el) -> StreamErrorInfo cond txt el)
(\(StreamErrorInfo cond txt el) ->((cond,() ,()), txt, el))
(xpElemNodes
(Name
"error"
(Just "http://etherx.jabber.org/streams")
(Just "stream")
)
(xp3Tuple
(xpElemByNamespace
"urn:ietf:params:xml:ns:xmpp-streams"
xpPrim
xpUnit
xpUnit
)
(xpOption $ xpElem
"{urn:ietf:params:xml:ns:xmpp-streams}text"
xpLangTag
(xpContent xpId)
)
(xpOption xpElemVerbatim) -- Application specific error conditions
)
)