use std::collections::HashSet;
use {
crate::prelude::Extension,
serde::{Deserialize, Serialize},
};
use crate::{media_types::RDAP_MEDIA_TYPE, prelude::ContentExtensions};
use super::{
types::{Link, Notice, NoticeOrRemark},
Common, CommonFields, ToResponse,
};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Rfc9083Error {
#[serde(flatten)]
pub common: Common,
#[serde(rename = "errorCode")]
pub error_code: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<Vec<String>>,
}
#[buildstructor::buildstructor]
impl Rfc9083Error {
#[builder(entry = "response_obj", visibility = "pub")]
fn new_response_obj(
error_code: u16,
notices: Vec<Notice>,
title: Option<String>,
description: Vec<String>,
extensions: Vec<Extension>,
) -> Self {
let notices = (!notices.is_empty()).then_some(notices);
Self {
common: Common::level0()
.extensions(extensions)
.and_notices(notices)
.build(),
error_code,
title,
description: Some(description),
}
}
#[builder(entry = "redirect", visibility = "pub")]
fn new_redirect(url: String, extensions: Vec<Extension>) -> Self {
let links = vec![Link::builder()
.href(&url)
.value(&url)
.media_type(RDAP_MEDIA_TYPE)
.rel("related")
.build()];
let notices = vec![Notice(NoticeOrRemark::builder().links(links).build())];
Self {
common: Common::level0()
.extensions(extensions)
.notices(notices)
.build(),
error_code: 307,
title: None,
description: None,
}
}
pub fn error_code(&self) -> u16 {
self.error_code
}
pub fn title(&self) -> Option<&str> {
self.title.as_deref()
}
pub fn description(&self) -> &[String] {
self.description.as_deref().unwrap_or_default()
}
pub fn is_redirect(&self) -> bool {
self.error_code > 299 && self.error_code < 400
}
}
impl CommonFields for Rfc9083Error {
fn common(&self) -> &Common {
&self.common
}
}
impl ToResponse for Rfc9083Error {
fn to_response(self) -> super::RdapResponse {
super::RdapResponse::ErrorResponse(Box::new(self))
}
}
impl ContentExtensions for Rfc9083Error {
fn content_extensions(&self) -> std::collections::HashSet<super::ExtensionId> {
let mut exts = HashSet::new();
exts.extend(self.common().content_extensions());
exts
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
use super::Rfc9083Error;
#[test]
fn GIVEN_error_code_301_WHEN_is_redirect_THEN_true() {
let e = Rfc9083Error::redirect().url("https://foo.example").build();
let actual = e.is_redirect();
assert!(actual);
}
#[test]
fn GIVEN_error_code_404_WHEN_is_redirect_THEN_false() {
let e = Rfc9083Error::response_obj().error_code(404).build();
let actual = e.is_redirect();
assert!(!actual);
}
}