1use crate::errors::{AllocateError, CreateError, DeleteError, RenameError};
5use cidr::IpCidr;
6use serde::de;
7use serde::ser::SerializeStruct;
8use std::str::FromStr;
9
10pub mod errors;
11pub mod pool;
12mod subspace;
13mod util;
14
15pub type CreateResult<T> = Result<T, CreateError>;
16
17pub type DeleteResult<T> = Result<T, DeleteError>;
18
19pub type AllocateResult<T> = Result<T, AllocateError>;
20
21pub type RenameResult<T> = Result<T, RenameError>;
22
23pub type Bits = u8;
24
25#[derive(Debug, Eq, Ord, PartialEq, PartialOrd, Clone)]
26pub struct CidrRecord {
27 pub cidr: IpCidr,
28 pub name: Option<String>,
29}
30
31impl CidrRecord {
32 pub(crate) fn new(cidr: IpCidr, name: Option<&str>) -> Self {
33 CidrRecord {
34 cidr,
35 name: name.map(|name| name.to_string()),
36 }
37 }
38}
39
40impl serde::Serialize for CidrRecord {
41 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42 where
43 S: serde::Serializer,
44 {
45 let mut structure = serializer.serialize_struct("CidrRecord", 2)?;
46 structure.serialize_field("cidr", &self.cidr.to_string())?;
47 if let Some(name) = &self.name {
48 structure.serialize_field("name", name)?;
49 }
50 structure.end()
51 }
52}
53
54impl<'s> serde::Deserialize<'s> for CidrRecord {
55 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
56 where
57 D: serde::Deserializer<'s>,
58 {
59 #[derive(serde::Deserialize)]
60 #[serde(field_identifier, rename_all = "lowercase")]
61 enum Field {
62 Cidr,
63 Name,
64 }
65 struct CidrRecordVisitor;
66 impl<'d> de::Visitor<'d> for CidrRecordVisitor {
67 type Value = CidrRecord;
68
69 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
70 formatter.write_str("struct CidrRecord")
71 }
72
73 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
74 where
75 A: de::SeqAccess<'d>,
76 {
77 let cidr_str = seq
78 .next_element::<&str>()?
79 .ok_or_else(|| de::Error::missing_field("cidr"))?;
80 let cidr = match IpCidr::from_str(cidr_str) {
81 Ok(cidr) => cidr,
82 Err(err) => return Err(serde::de::Error::custom(err)),
83 };
84
85 let name = seq
86 .next_element::<Option<&str>>()?
87 .ok_or_else(|| serde::de::Error::missing_field("name"))?;
88
89 Ok(CidrRecord::new(cidr, name))
90 }
91 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
92 where
93 A: de::MapAccess<'d>,
94 {
95 let mut cidr: Option<IpCidr> = None;
96 let mut name: Option<String> = None;
97 while let Some(key) = map.next_key()? {
98 match key {
99 Field::Cidr => {
100 if cidr.is_some() {
101 return Err(de::Error::duplicate_field("cidr"));
102 }
103 cidr = match map.next_value::<String>() {
104 Ok(cidr) => match IpCidr::from_str(cidr.as_str()) {
105 Ok(cidr) => Some(cidr),
106 Err(err) => return Err(de::Error::custom(err)),
107 },
108 Err(err) => return Err(err),
109 };
110 }
111 Field::Name => {
112 if name.is_some() {
113 return Err(de::Error::duplicate_field("name"));
114 }
115 name = Some(map.next_value()?);
116 }
117 }
118 }
119 let cidr = match cidr {
120 Some(cidr) => cidr,
121 None => return Err(de::Error::missing_field("cidr")),
122 };
123 Ok(CidrRecord::new(cidr, name.as_deref()))
124 }
125 }
126
127 deserializer.deserialize_struct("CidrRecord", &["cidr", "name"], CidrRecordVisitor)
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134 use cidr::{Ipv4Cidr, Ipv6Cidr};
135 use std::net::{Ipv4Addr, Ipv6Addr};
136
137 pub static TEST_CIDR4: IpCidr =
138 IpCidr::V4(match Ipv4Cidr::new(Ipv4Addr::new(10, 20, 0, 0), 16) {
139 Ok(cidr) => cidr,
140 _ => panic!("Failed to create test v4 cidr"),
141 });
142
143 pub static TEST_CIDR6: IpCidr = IpCidr::V6(
144 match Ipv6Cidr::new(Ipv6Addr::new(1, 2, 3, 4, 10, 20, 0, 0), 112) {
145 Ok(cidr) => cidr,
146 _ => panic!("Failed to create test v6 cidr"),
147 },
148 );
149 mod cidr_record {
150 use super::*;
151 use serde_test::{assert_de_tokens_error, assert_tokens};
152 use std::str::FromStr;
153
154 #[test]
155 fn new() {
156 let cidr = IpCidr::from_str("10.20.30.0/24").unwrap();
157 let name = Some("foo");
158 let record = super::super::CidrRecord::new(cidr, name);
159 assert_eq!(record.cidr, cidr);
160 assert_eq!(record.name.as_deref(), name);
161 }
162
163 #[test]
164 fn serialize_named() {
165 let cidr = IpCidr::from_str("10.20.30.0/24").unwrap();
166 let record = CidrRecord::new(cidr, Some("a-record"));
167 assert_tokens(
168 &record,
169 &[
170 serde_test::Token::Struct {
171 name: "CidrRecord",
172 len: 2,
173 },
174 serde_test::Token::Str("cidr"),
175 serde_test::Token::Str("10.20.30.0/24"),
176 serde_test::Token::Str("name"),
177 serde_test::Token::Str("a-record"),
178 serde_test::Token::StructEnd,
179 ],
180 );
181 }
182
183 #[test]
184 fn serialize_unnamed() {
185 let cidr = IpCidr::from_str("10.20.30.0/24").unwrap();
186 let record = CidrRecord::new(cidr, None);
187 assert_tokens(
188 &record,
189 &[
190 serde_test::Token::Struct {
191 name: "CidrRecord",
192 len: 2,
193 },
194 serde_test::Token::Str("cidr"),
195 serde_test::Token::Str("10.20.30.0/24"),
196 serde_test::Token::StructEnd,
197 ],
198 );
199 }
200
201 #[test]
202 fn deserialize_as_sequence() {
203 assert_de_tokens_error::<CidrRecord>(
204 &[
205 serde_test::Token::Struct {
206 name: "CidrRecord",
207 len: 2,
208 },
209 serde_test::Token::Str("cidr"),
210 serde_test::Token::Str("invalid"),
211 serde_test::Token::StructEnd,
212 ],
213 "couldn't parse address in network: invalid IP address syntax",
214 );
215 }
216 }
217}