//! Request Message //! //! All messages that clients can send to relayers are abstracted in this mod use crate::{client, common::SerializeDeserialize, types}; use serde::{ de::{self, Deserializer}, ser::{self, SerializeSeq, Serializer}, Deserialize, }; use std::collections::VecDeque; custom_derive! { #[derive(Debug, Clone, EnumFromInner)] /// Request Messages /// /// All requests from clients to relayer are abstracted in this struct pub enum Request { /// Close a subscription Close(client::Close), /// An Event from a client. This is when a client wants to publish an /// event. The event must be signed. Event(client::Event), /// Creates a subscription. Client tells the relayer which kind of events /// they'd like to hear about Request(client::Subscribe), } } impl Request { /// Returns the current message as a Request, if possible pub fn as_request(&self) -> Option<&client::Subscribe> { match self { Self::Request(x) => Some(x), _ => None, } } /// Returns the current message as a close if possible pub fn as_close(&self) -> Option<&client::Close> { match self { Self::Close(t) => Some(t), _ => None, } } /// Returns the current message as an event from the client, if possible pub fn as_event(&self) -> Option<&types::Event> { match self { Self::Event(event) => Some(&**event), _ => None, } } } impl From for Request { fn from(event: types::Event) -> Self { Self::Event(event.into()) } } impl ser::Serialize for Request { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let values = match self { Self::Close(t) => t.serialize(), Self::Event(t) => t.serialize(), Self::Request(t) => t.serialize(), } .map_err(ser::Error::custom)?; let mut seq = serializer.serialize_seq(Some(values.len()))?; for value in values.iter() { seq.serialize_element(value)?; } seq.end() } } impl<'de> de::Deserialize<'de> for Request { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let mut array: VecDeque = Deserialize::deserialize(deserializer)?; if array.is_empty() { return Err(de::Error::custom( "Invalid array length, expecting at least one", )); } let tag = array .remove(0) .ok_or_else(|| de::Error::custom("Invalid array length, expecting at least one"))?; let tag = tag .as_str() .ok_or_else(|| de::Error::custom("Invalid type for element 0 of the array"))?; match tag { "EVENT" => Ok(client::Event::deserialize(array) .map_err(de::Error::custom)? .into()), "CLOSE" => Ok(client::Close::deserialize(array) .map_err(de::Error::custom)? .into()), "REQ" => Ok(client::Subscribe::deserialize(array) .map_err(de::Error::custom)? .into()), tag => Err(de::Error::custom(format!("{} is not a support tag", tag))), } } } #[cfg(test)] mod test { use super::*; #[test] fn unsupported() { let json = "[\"CLOSEX\", \"foo\"]"; let message: Result = serde_json::from_str(json); assert!(message.is_err()); } #[test] fn close() { let json = "[\"CLOSE\", \"foo\"]"; let message: Request = serde_json::from_str(json).expect("valid message"); let subscription_id = message.as_close().expect("valid subscription_id"); assert_eq!("foo".to_owned(), subscription_id.to_string()); } }