rama_http/layer/dns/dns_resolve/
mod.rs1use crate::HeaderValue;
9use rama_core::error::BoxErrorExt as _;
10use rama_core::error::{BoxError, ErrorContext as _, ErrorExt};
11use rama_core::extensions::Extension;
12use rama_core::username::{ComposeError, Composer, UsernameLabelWriter};
13use rama_utils::macros::match_ignore_ascii_case_str;
14use std::fmt;
15
16mod service;
17#[doc(inline)]
18pub use service::DnsResolveModeService;
19
20mod layer;
21#[doc(inline)]
22pub use layer::DnsResolveModeLayer;
23
24mod username_parser;
25#[doc(inline)]
26pub use username_parser::DnsResolveModeUsernameParser;
27
28#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Extension)]
29#[extension(tags(http, dns))]
30pub struct DnsResolveMode(ResolveMode);
34
35impl fmt::Display for DnsResolveMode {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self.0 {
38 ResolveMode::Eager => write!(f, "eager"),
39 ResolveMode::Lazy => write!(f, "lazy"),
40 }
41 }
42}
43
44impl DnsResolveMode {
45 #[must_use]
47 pub const fn eager() -> Self {
48 Self(ResolveMode::Eager)
49 }
50
51 #[must_use]
53 pub const fn lazy() -> Self {
54 Self(ResolveMode::Lazy)
55 }
56
57 #[must_use]
59 pub fn is_eager(&self) -> bool {
60 match self.0 {
61 ResolveMode::Eager => true,
62 ResolveMode::Lazy => false,
63 }
64 }
65
66 #[must_use]
68 pub fn is_lazy(&self) -> bool {
69 match self.0 {
70 ResolveMode::Eager => false,
71 ResolveMode::Lazy => true,
72 }
73 }
74}
75
76impl std::str::FromStr for DnsResolveMode {
77 type Err = BoxError;
78
79 #[inline(always)]
80 fn from_str(value: &str) -> Result<Self, Self::Err> {
81 Self::try_from(value)
82 }
83}
84
85impl TryFrom<&str> for DnsResolveMode {
86 type Error = BoxError;
87
88 fn try_from(value: &str) -> Result<Self, Self::Error> {
89 match_ignore_ascii_case_str! {
90 match (value) {
91 "eager" => Ok(Self::eager()),
92 "lazy" => Ok(Self::lazy()),
93 _ => Err(BoxError::from_static_str("Invalid DNS resolve mode: unknown str")),
94 }
95 }
96 }
97}
98
99impl TryFrom<&HeaderValue> for DnsResolveMode {
100 type Error = BoxError;
101
102 fn try_from(value: &HeaderValue) -> Result<Self, Self::Error> {
103 match value.to_str() {
104 Ok(value) => Self::try_from(value).into_box_error(),
105 Err(err) => Err(err.context("Invalid DNS resolve mode")),
106 }
107 }
108}
109
110#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
111enum ResolveMode {
112 Eager,
113 #[default]
114 Lazy,
115}
116
117impl<const SEPARATOR: char> UsernameLabelWriter<SEPARATOR> for DnsResolveMode {
118 fn write_labels(&self, composer: &mut Composer<SEPARATOR>) -> Result<(), ComposeError> {
119 composer.write_label("dns")?;
120 match self.0 {
121 ResolveMode::Eager => composer.write_label("eager"),
122 ResolveMode::Lazy => composer.write_label("lazy"),
123 }
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use rama_core::extensions::Extensions;
131 use rama_core::username::{compose_username, parse_username};
132
133 #[test]
134 fn parse_username_label_compose_parse_dns_resolve_mode() {
135 let test_cases = [DnsResolveMode::eager(), DnsResolveMode::lazy()];
136 for test_case in test_cases {
137 let fmt_username = compose_username("john".to_owned(), test_case).unwrap();
138 let ext = Extensions::new();
139 let username =
140 parse_username(&ext, DnsResolveModeUsernameParser::default(), fmt_username)
141 .unwrap();
142 assert_eq!("john", username);
143 let result = ext.get_ref::<DnsResolveMode>().unwrap();
144 assert_eq!(test_case, *result);
145 }
146 }
147}