whois_rust/
who_is_server_value.rs1use std::borrow::Cow;
2
3use serde_json::Value;
4use validators::prelude::*;
5
6use crate::{WhoIsError, WhoIsHost};
7
8const DEFAULT_PUNYCODE: bool = true;
9
10#[derive(Debug, Clone)]
12pub struct WhoIsServerValue {
13 pub host: WhoIsHost,
14 pub query: Option<String>,
15 pub punycode: bool,
16}
17
18impl WhoIsServerValue {
19 pub fn from_value(value: &Value) -> Result<WhoIsServerValue, WhoIsError> {
20 match value {
21 Value::Object(map) => match map.get("host") {
22 Some(Value::String(host)) => {
23 let host = match WhoIsHost::parse_str(host) {
24 Ok(host) => host,
25 Err(_) => {
26 return Err(WhoIsError::MapError(
27 "The server value is an object, but it has not a correct host \
28 string.",
29 ));
30 },
31 };
32
33 let query = match map.get("query") {
34 Some(query) => {
35 if let Value::String(query) = query {
36 Some(String::from(query))
37 } else {
38 return Err(WhoIsError::MapError(
39 "The server value is an object, but it has an incorrect query \
40 string.",
41 ));
42 }
43 },
44 None => None,
45 };
46
47 let punycode = match map.get("punycode") {
48 Some(punycode) => {
49 if let Value::Bool(punycode) = punycode {
50 *punycode
51 } else {
52 return Err(WhoIsError::MapError(
53 "The server value is an object, but it has an incorrect \
54 punycode boolean value.",
55 ));
56 }
57 },
58 None => DEFAULT_PUNYCODE,
59 };
60
61 Ok(WhoIsServerValue {
62 host,
63 query,
64 punycode,
65 })
66 },
67 _ => Err(WhoIsError::MapError(
68 "The server value is an object, but it has not a host string.",
69 )),
70 },
71 Value::String(host) => Self::from_string(host),
72 _ => Err(WhoIsError::MapError("The server value is not an object or a host string.")),
73 }
74 }
75
76 #[inline]
77 pub fn from_string<S: AsRef<str>>(string: S) -> Result<WhoIsServerValue, WhoIsError> {
78 let host = string.as_ref();
79
80 let host = match WhoIsHost::parse_str(host) {
81 Ok(host) => host,
82 Err(_) => {
83 return Err(WhoIsError::MapError("The server value is not a correct host string."));
84 },
85 };
86
87 Ok(WhoIsServerValue {
88 host,
89 query: None,
90 punycode: DEFAULT_PUNYCODE,
91 })
92 }
93
94 pub(crate) fn encode_domain<'a>(&self, domain: &'a str) -> Cow<'a, str> {
96 if self.punycode {
97 Cow::Borrowed(domain)
98 } else {
99 Cow::Owned(validators::idna::domain_to_unicode(domain).0)
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn encode_domain_honors_punycode_flag() {
110 let mut server = WhoIsServerValue::from_string("whois.denic.de").unwrap();
111
112 assert_eq!("xn--mller-kva.de", server.encode_domain("xn--mller-kva.de").as_ref());
114
115 server.punycode = false;
117 assert_eq!("müller.de", server.encode_domain("xn--mller-kva.de").as_ref());
118 }
119}