1use std::fmt::Debug;
4
5use instant_xml::{FromXmlOwned, ToXml};
6
7use crate::common::EPP_XMLNS;
8
9pub const EPP_VERSION: &str = "1.0";
10pub const EPP_LANG: &str = "en";
11
12pub trait Transaction<Ext: Extension>: Command + Sized {}
14
15pub trait Command: ToXml + Debug {
16 type Response: FromXmlOwned + Debug;
17 const COMMAND: &'static str;
18}
19
20pub trait Extension: ToXml + Debug {
21 type Response: FromXmlOwned + Debug;
22}
23
24#[derive(Debug, PartialEq)]
25pub(crate) struct CommandWrapper<'a, D, E> {
28 command: &'static str,
29 data: &'a D,
31 extension: Option<&'a E>,
33 client_tr_id: String,
34}
35
36impl<'a, E: Extension, D: Transaction<E>> CommandWrapper<'a, D, E> {
37 pub(crate) fn new(data: &'a D, extension: Option<&'a E>, client_tr_id: &'a str) -> Self {
38 Self {
39 command: D::COMMAND,
40 data,
41 extension,
42 client_tr_id: client_tr_id.into(),
43 }
44 }
45}
46
47impl<'a, D: ToXml, E: ToXml> ToXml for CommandWrapper<'a, D, E> {
48 fn serialize<W: std::fmt::Write + ?Sized>(
49 &self,
50 _: Option<instant_xml::Id<'_>>,
51 serializer: &mut instant_xml::Serializer<W>,
52 ) -> Result<(), instant_xml::Error> {
53 let prefix = serializer.write_start("command", EPP_XMLNS)?;
54 serializer.end_start()?;
55 self.data.serialize(None, serializer)?;
56 if let Some(extension) = self.extension {
57 Ext { inner: extension }.serialize(None, serializer)?;
58 }
59
60 let id_prefix = serializer.write_start("clTRID", EPP_XMLNS)?;
61 serializer.end_start()?;
62 serializer.write_str(&self.client_tr_id)?;
63 serializer.write_close(id_prefix, "clTRID")?;
64
65 serializer.write_close(prefix, "command")?;
66 Ok(())
67 }
68}
69
70#[derive(Debug, ToXml)]
71#[xml(rename = "extension", ns(EPP_XMLNS))]
72struct Ext<E> {
73 inner: E,
74}