epp_client/
request.rs

1//! Types for EPP requests
2
3use serde::{de::DeserializeOwned, ser::SerializeStruct, ser::Serializer, Serialize};
4use std::fmt::Debug;
5
6use crate::common::{StringValue, EPP_XMLNS};
7
8pub const EPP_VERSION: &str = "1.0";
9pub const EPP_LANG: &str = "en";
10
11/// Trait to set correct value for xml tags when tags are being generated from generic types
12pub trait Transaction<Ext: Extension>: Command + Sized {}
13
14pub trait Command: Serialize + Debug {
15    type Response: DeserializeOwned + Debug;
16    const COMMAND: &'static str;
17}
18
19pub trait Extension: Serialize + Debug {
20    type Response: DeserializeOwned + Debug;
21}
22
23#[derive(Debug, PartialEq)]
24/// Type corresponding to the &lt;command&gt; tag in an EPP XML request
25/// with an &lt;extension&gt; tag
26struct CommandWrapper<'a, D, E> {
27    pub command: &'static str,
28    /// The instance that will be used to populate the &lt;command&gt; tag
29    pub data: &'a D,
30    /// The client TRID
31    pub extension: Option<&'a E>,
32    pub client_tr_id: StringValue<'a>,
33}
34
35impl<'a, D: Serialize, E: Serialize> Serialize for CommandWrapper<'a, D, E> {
36    /// Serializes the generic type T to the proper XML tag (set by the `#[element_name(name = <tagname>)]` attribute) for the request
37    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38    where
39        S: Serializer,
40    {
41        let mut state = serializer.serialize_struct("command", 3)?;
42        state.serialize_field(self.command, self.data)?;
43        state.serialize_field("extension", &self.extension)?;
44        state.serialize_field("clTRID", &self.client_tr_id)?;
45        state.end()
46    }
47}
48
49#[derive(Debug, PartialEq, Serialize)]
50#[serde(rename = "epp")]
51pub(crate) struct CommandDocument<'a, Cmd, Ext> {
52    xmlns: &'static str,
53    command: CommandWrapper<'a, Cmd, Ext>,
54}
55
56impl<'a, Cmd, Ext> CommandDocument<'a, Cmd, Ext> {
57    pub(crate) fn new(data: &'a Cmd, extension: Option<&'a Ext>, client_tr_id: &'a str) -> Self
58    where
59        Cmd: Transaction<Ext>,
60        Ext: Extension,
61    {
62        Self {
63            xmlns: EPP_XMLNS,
64            command: CommandWrapper {
65                command: Cmd::COMMAND,
66                data,
67                extension,
68                client_tr_id: client_tr_id.into(),
69            },
70        }
71    }
72}