Use enum type to represent host::Status

This commit is contained in:
Dirkjan Ochtman 2023-03-02 14:08:02 +01:00
parent 96268d9528
commit f2194c818c
5 changed files with 107 additions and 18 deletions

View File

@ -56,7 +56,7 @@ pub struct InfoData {
pub roid: String,
/// The list of host statuses
#[xml(rename = "status")]
pub statuses: Vec<Status<'static>>,
pub statuses: Vec<Status>,
/// The list of host IP addresses
#[xml(rename = "addr", deserialize_with = "deserialize_host_addrs")]
pub addresses: Vec<IpAddr>,
@ -119,6 +119,7 @@ mod tests {
use chrono::{TimeZone, Utc};
use super::{HostInfo, IpAddr};
use crate::host::Status;
use crate::response::ResultCode;
use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID};
@ -137,7 +138,7 @@ mod tests {
assert_eq!(object.result.message, SUCCESS_MSG);
assert_eq!(result.name, "host2.eppdev-1.com");
assert_eq!(result.roid, "UNDEF-ROID");
assert_eq!(result.statuses[0].status, "ok".to_string());
assert_eq!(result.statuses[0], Status::Ok);
assert_eq!(result.addresses[0], IpAddr::from([29, 245, 122, 14]));
assert_eq!(
result.addresses[1],

View File

@ -6,7 +6,7 @@ use std::borrow::Cow;
use std::fmt;
use std::net::IpAddr;
use instant_xml::{FromXml, Serializer, ToXml};
use instant_xml::{Deserializer, FromXml, Serializer, ToXml};
pub mod check;
pub use check::HostCheck;
@ -26,12 +26,103 @@ pub use update::HostUpdate;
pub const XMLNS: &str = "urn:ietf:params:xml:ns:host-1.0";
/// The `<status>` type on contact transactions
#[derive(Debug, FromXml, ToXml)]
#[xml(rename = "status", ns(XMLNS))]
pub struct Status<'a> {
/// The status name, represented by the 's' attr on `<status>` tags
#[xml(attribute, rename = "s")]
pub status: Cow<'a, str>,
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Status {
ClientDeleteProhibited,
ServerDeleteProhibited,
ClientUpdateProhibited,
ServerUpdateProhibited,
Linked,
Ok,
PendingCreate,
PendingDelete,
PendingTransfer,
PendingUpdate,
}
impl Status {
pub fn as_str(&self) -> &'static str {
use Status::*;
match self {
ClientDeleteProhibited => "clientDeleteProhibited",
ServerDeleteProhibited => "serverDeleteProhibited",
ClientUpdateProhibited => "clientUpdateProhibited",
ServerUpdateProhibited => "serverUpdateProhibited",
Linked => "linked",
Ok => "ok",
PendingCreate => "pendingCreate",
PendingDelete => "pendingDelete",
PendingTransfer => "pendingTransfer",
PendingUpdate => "pendingUpdate",
}
}
}
impl ToXml for Status {
fn serialize<W: fmt::Write + ?Sized>(
&self,
_: Option<instant_xml::Id<'_>>,
serializer: &mut Serializer<W>,
) -> Result<(), instant_xml::Error> {
serializer.write_start("status", XMLNS)?;
serializer.write_attr("s", XMLNS, &self.as_str())?;
serializer.end_empty()
}
}
impl<'xml> FromXml<'xml> for Status {
fn matches(id: instant_xml::Id<'_>, _: Option<instant_xml::Id<'_>>) -> bool {
id == instant_xml::Id {
ns: XMLNS,
name: "status",
}
}
fn deserialize<'cx>(
into: &mut Self::Accumulator,
field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), instant_xml::Error> {
use instant_xml::de::Node;
use instant_xml::{Error, Id};
let node = match deserializer.next() {
Some(result) => result?,
None => return Err(Error::MissingValue(field)),
};
let attr = match node {
Node::Attribute(attr) => attr,
Node::Open(_) | Node::Text(_) => return Err(Error::MissingValue(field)),
node => return Err(Error::UnexpectedNode(format!("{node:?} in Status"))),
};
let id = deserializer.attribute_id(&attr)?;
let expected = Id { ns: "", name: "s" };
if id != expected {
return Err(Error::MissingValue(field));
}
*into = Some(match attr.value {
"clientDeleteProhibited" => Status::ClientDeleteProhibited,
"serverDeleteProhibited" => Status::ServerDeleteProhibited,
"clientUpdateProhibited" => Status::ClientUpdateProhibited,
"serverUpdateProhibited" => Status::ServerUpdateProhibited,
"linked" => Status::Linked,
"ok" => Status::Ok,
"pendingCreate" => Status::PendingCreate,
"pendingDelete" => Status::PendingDelete,
"pendingTransfer" => Status::PendingTransfer,
"pendingUpdate" => Status::PendingUpdate,
val => return Err(Error::UnexpectedValue(format!("invalid status {val:?}"))),
});
deserializer.ignore()?;
Ok(())
}
type Accumulator = Option<Status>;
const KIND: instant_xml::Kind = instant_xml::Kind::Element;
}
/// The `<hostAddr>` types domain or host transactions

View File

@ -60,7 +60,7 @@ pub struct HostAdd<'a> {
pub addresses: Option<&'a [IpAddr]>,
/// The statuses to be added to or removed from the host
#[xml(rename = "host:status")]
pub statuses: Option<&'a [Status<'a>]>,
pub statuses: Option<&'a [Status]>,
}
/// Type for data under the `<add>` and `<rem>` tags
@ -72,7 +72,7 @@ pub struct HostRemove<'a> {
pub addresses: Option<&'a [IpAddr]>,
/// The statuses to be added to or removed from the host
#[xml(rename = "host:status")]
pub statuses: Option<&'a [Status<'a>]>,
pub statuses: Option<&'a [Status]>,
}
/// Type for data under the host `<update>` tag
@ -118,13 +118,9 @@ mod tests {
statuses: None,
};
let statuses = &[Status {
status: "clientDeleteProhibited".into(),
}];
let remove = HostRemove {
addresses: None,
statuses: Some(statuses),
statuses: Some(&[Status::ClientDeleteProhibited]),
};
let mut object = HostUpdate::new("host1.eppdev-1.com");

View File

@ -48,6 +48,7 @@ pub enum MessagePollResponse {
#[cfg(test)]
mod tests {
use super::{MessagePoll, MessagePollResponse};
use crate::host::Status;
use crate::response::ResultCode;
use crate::tests::{assert_serialized, response_from_file, CLTRID, SVTRID};
@ -133,7 +134,7 @@ mod tests {
assert_eq!(host.name, "ns.test.com");
assert_eq!(host.roid, "1234");
assert!(host.statuses.iter().any(|s| s.status == "ok"));
assert!(host.statuses.iter().any(|&s| s == Status::Ok));
assert!(host
.addresses
.iter()

View File

@ -8,7 +8,7 @@
<addr ip="v6">2404:6800:4001:801::200e</addr>
</add>
<rem>
<status s="clientDeleteProhibited"></status>
<status s="clientDeleteProhibited" />
</rem>
<chg>
<name>host2.eppdev-1.com</name>