use std::collections::HashSet;
use crate::prelude::ContentExtensions;
use {
crate::prelude::{Common, Extension, ObjectCommon},
serde::{Deserialize, Serialize},
};
use super::{
to_opt_vec, types::Link, CommonFields, Entity, Event, GetSelfLink, Notice, Numberish,
ObjectCommonFields, Port43, Remark, SelfLink, Stringish, ToChild, ToResponse,
};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Autnum {
#[serde(flatten)]
pub common: Common,
#[serde(flatten)]
pub object_common: ObjectCommon,
#[serde(rename = "startAutnum")]
#[serde(skip_serializing_if = "Option::is_none")]
pub start_autnum: Option<Numberish<u32>>,
#[serde(rename = "endAutnum")]
#[serde(skip_serializing_if = "Option::is_none")]
pub end_autnum: Option<Numberish<u32>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<Stringish>,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub autnum_type: Option<Stringish>,
#[serde(skip_serializing_if = "Option::is_none")]
pub country: Option<Stringish>,
}
#[buildstructor::buildstructor]
impl Autnum {
#[builder(visibility = "pub")]
fn new(
autnum_range: std::ops::Range<u32>,
handle: Option<String>,
remarks: Vec<Remark>,
links: Vec<Link>,
events: Vec<Event>,
statuses: Vec<String>,
port_43: Option<Port43>,
entities: Vec<Entity>,
country: Option<String>,
autnum_type: Option<String>,
name: Option<String>,
redacted: Option<Vec<crate::response::redacted::Redacted>>,
) -> Self {
Self {
common: Common::builder().build(),
object_common: ObjectCommon::autnum()
.and_handle(handle.map(|s| s.into()) as Option<Stringish>)
.and_remarks(to_opt_vec(remarks))
.and_links(to_opt_vec(links))
.and_events(to_opt_vec(events))
.status(statuses)
.and_port_43(port_43)
.and_entities(to_opt_vec(entities))
.and_redacted(redacted)
.build(),
start_autnum: Some(Numberish::<u32>::from(autnum_range.start)),
end_autnum: Some(Numberish::<u32>::from(autnum_range.end)),
name: name.map(|s| s.into()),
autnum_type: autnum_type.map(|s| s.into()),
country: country.map(|s| s.into()),
}
}
#[builder(entry = "response_obj", visibility = "pub")]
fn new_response_obj(
autnum_range: std::ops::Range<u32>,
handle: Option<String>,
remarks: Vec<Remark>,
links: Vec<Link>,
events: Vec<Event>,
statuses: Vec<String>,
port_43: Option<Port43>,
entities: Vec<Entity>,
notices: Vec<Notice>,
country: Option<String>,
autnum_type: Option<String>,
name: Option<String>,
extensions: Vec<Extension>,
redacted: Option<Vec<crate::response::redacted::Redacted>>,
) -> Self {
let common = Common::level0()
.extensions(extensions)
.and_notices(to_opt_vec(notices))
.build();
let mut autnum = Autnum::builder()
.autnum_range(autnum_range)
.and_handle(handle)
.remarks(remarks)
.links(links)
.events(events)
.statuses(statuses)
.and_port_43(port_43)
.entities(entities)
.and_country(country)
.and_autnum_type(autnum_type)
.and_name(name)
.and_redacted(redacted)
.build();
autnum.common = common;
autnum
}
pub fn start_autnum(&self) -> Option<u32> {
self.start_autnum.as_ref().and_then(|n| n.as_u32())
}
pub fn end_autnum(&self) -> Option<u32> {
self.end_autnum.as_ref().and_then(|n| n.as_u32())
}
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn autnum_type(&self) -> Option<&str> {
self.autnum_type.as_deref()
}
pub fn country(&self) -> Option<&str> {
self.country.as_deref()
}
}
impl ToResponse for Autnum {
fn to_response(self) -> super::RdapResponse {
super::RdapResponse::Autnum(Box::new(self))
}
}
impl GetSelfLink for Autnum {
fn self_link(&self) -> Option<&Link> {
self.object_common.self_link()
}
}
impl SelfLink for Autnum {
fn with_self_link(mut self, link: Link) -> Self {
self.object_common = self.object_common.with_self_link(link);
self
}
}
impl ToChild for Autnum {
fn to_child(mut self) -> Self {
self.common = Common {
rdap_conformance: None,
notices: None,
};
self
}
}
impl CommonFields for Autnum {
fn common(&self) -> &Common {
&self.common
}
}
impl ObjectCommonFields for Autnum {
fn object_common(&self) -> &ObjectCommon {
&self.object_common
}
}
impl ContentExtensions for Autnum {
fn content_extensions(&self) -> std::collections::HashSet<super::ExtensionId> {
let mut exts = HashSet::new();
exts.extend(self.common().content_extensions());
exts.extend(self.object_common().content_extensions());
exts
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
use super::Autnum;
#[test]
fn GIVEN_autnum_WHEN_deserialize_THEN_success() {
let expected = r#"
{
"objectClassName" : "autnum",
"handle" : "XXXX-RIR",
"startAutnum" : 65536,
"endAutnum" : 65541,
"name": "AS-RTR-1",
"type" : "DIRECT ALLOCATION",
"status" : [ "active" ],
"country": "AU",
"remarks" :
[
{
"description" :
[
"She sells sea shells down by the sea shore.",
"Originally written by Terry Sullivan."
]
}
],
"links" :
[
{
"value" : "https://example.net/autnum/65537",
"rel" : "self",
"href" : "https://example.net/autnum/65537",
"type" : "application/rdap+json"
}
],
"events" :
[
{
"eventAction" : "registration",
"eventDate" : "1990-12-31T23:59:59Z"
},
{
"eventAction" : "last changed",
"eventDate" : "1991-12-31T23:59:59Z"
}
],
"entities" :
[
{
"objectClassName" : "entity",
"handle" : "XXXX",
"vcardArray":[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "Joe User"],
["kind", {}, "text", "individual"],
["lang", {
"pref":"1"
}, "language-tag", "fr"],
["lang", {
"pref":"2"
}, "language-tag", "en"],
["org", {
"type":"work"
}, "text", "Example"],
["title", {}, "text", "Research Scientist"],
["role", {}, "text", "Project Lead"],
["adr",
{ "type":"work" },
"text",
[
"",
"Suite 1234",
"4321 Rue Somewhere",
"Quebec",
"QC",
"G1V 2M2",
"Canada"
]
],
["tel",
{ "type":["work", "voice"], "pref":"1" },
"uri", "tel:+1-555-555-1234;ext=102"
],
["email",
{ "type":"work" },
"text", "joe.user@example.com"
]
]
],
"roles" : [ "registrant" ],
"remarks" :
[
{
"description" :
[
"She sells sea shells down by the sea shore.",
"Originally written by Terry Sullivan."
]
}
],
"links" :
[
{
"value" : "https://example.net/entity/XXXX",
"rel" : "self",
"href" : "https://example.net/entity/XXXX",
"type" : "application/rdap+json"
}
],
"events" :
[
{
"eventAction" : "registration",
"eventDate" : "1990-12-31T23:59:59Z"
},
{
"eventAction" : "last changed",
"eventDate" : "1991-12-31T23:59:59Z"
}
]
}
]
}
"#;
let actual = serde_json::from_str::<Autnum>(expected);
let actual = actual.unwrap();
assert_eq!(actual.object_common.object_class_name, "autnum");
assert!(actual.object_common.handle.is_some());
assert!(actual.start_autnum.is_some());
assert!(actual.end_autnum.is_some());
assert!(actual.name.is_some());
assert!(actual.autnum_type.is_some());
assert!(actual.object_common.status.is_some());
assert!(actual.country.is_some());
assert!(actual.object_common.remarks.is_some());
assert!(actual.object_common.links.is_some());
assert!(actual.object_common.events.is_some());
assert!(actual.object_common.entities.is_some());
}
}