1use 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
11pub 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)]
24struct CommandWrapper<'a, D, E> {
27 pub command: &'static str,
28 pub data: &'a D,
30 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 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}