rpsl_parser/rpsl.rs
1//! Types for representing RPSL components.
2use std::{ops::Index, option::Option};
3
4/// Represents a RPSL attribute.
5#[derive(Debug, PartialEq, Eq)]
6pub struct Attribute {
7 /// The name of the attribute.
8 pub name: String,
9 /// The values of the attribute.
10 /// Single line attributes only have one value, while for multi-line attributes every line is a value.
11 /// An empty value or one containing only whitespace is represented as None.
12 pub values: Vec<Option<String>>,
13}
14
15impl Attribute {
16 /// Create a new RPSL attribute from a name and vector of values.
17 #[must_use]
18 pub fn new(name: String, values: Vec<Option<String>>) -> Self {
19 Attribute { name, values }
20 }
21}
22
23/// Create a RPSL attribute from a tuple of slices parsed from RPSL text.
24/// An empty value or one containing only whitespace is converted to None.
25impl From<(&str, Vec<&str>)> for Attribute {
26 fn from(attribute_slice: (&str, Vec<&str>)) -> Self {
27 let (name, values) = attribute_slice;
28
29 Attribute {
30 name: name.to_string(),
31 values: values
32 .iter()
33 .map(|v| {
34 if v.trim().is_empty() {
35 return None;
36 }
37 Some((*v).to_string())
38 })
39 .collect(),
40 }
41 }
42}
43
44/// Represents a RPSL object.
45///
46/// # Examples
47///
48/// Create a new role object
49/// ```
50/// # use rpsl_parser::rpsl;
51/// let role_acme = rpsl::Object::new(vec![
52/// rpsl::Attribute::new("role".to_string(), vec![Some("ACME Company".to_string())]),
53/// rpsl::Attribute::new(
54/// "address".to_string(),
55/// vec![Some("Packet Street 6".to_string())],
56/// ),
57/// rpsl::Attribute::new(
58/// "address".to_string(),
59/// vec![Some("128 Series of Tubes".to_string())],
60/// ),
61/// rpsl::Attribute::new("address".to_string(), vec![Some("Internet".to_string())]),
62/// rpsl::Attribute::new(
63/// "email".to_string(),
64/// vec![Some("rpsl-parser@github.com".to_string())],
65/// ),
66/// rpsl::Attribute::new("nic-hdl".to_string(), vec![Some("RPSL1-RIPE".to_string())]),
67/// rpsl::Attribute::new("source".to_string(), vec![Some("RIPE".to_string())]),
68/// ]);
69/// ```
70///
71/// And then print the `email` attribute by it's index
72/// ```
73/// # use rpsl_parser::rpsl;
74/// # let role_acme = rpsl::Object::new(vec![
75/// # rpsl::Attribute::new("role".to_string(), vec![Some("ACME Company".to_string())]),
76/// # rpsl::Attribute::new(
77/// # "address".to_string(),
78/// # vec![Some("Packet Street 6".to_string())],
79/// # ),
80/// # rpsl::Attribute::new(
81/// # "address".to_string(),
82/// # vec![Some("128 Series of Tubes".to_string())],
83/// # ),
84/// # rpsl::Attribute::new("address".to_string(), vec![Some("Internet".to_string())]),
85/// # rpsl::Attribute::new(
86/// # "email".to_string(),
87/// # vec![Some("rpsl-parser@github.com".to_string())],
88/// # ),
89/// # rpsl::Attribute::new("nic-hdl".to_string(), vec![Some("RPSL1-RIPE".to_string())]),
90/// # rpsl::Attribute::new("source".to_string(), vec![Some("RIPE".to_string())]),
91/// # ]);
92/// println!("{:#?}", role_acme[4]);
93/// ```
94#[derive(Debug, PartialEq, Eq)]
95pub struct Object(Vec<Attribute>);
96
97impl Object {
98 /// Create a new RPSL object from a vector of attributes.
99 #[must_use]
100 pub fn new(attributes: Vec<Attribute>) -> Self {
101 Object(attributes)
102 }
103}
104
105impl Index<usize> for Object {
106 type Output = Attribute;
107
108 fn index(&self, index: usize) -> &Self::Output {
109 &self.0[index]
110 }
111}
112
113impl IntoIterator for Object {
114 type Item = Attribute;
115 type IntoIter = std::vec::IntoIter<Attribute>;
116
117 fn into_iter(self) -> Self::IntoIter {
118 self.0.into_iter()
119 }
120}
121
122// Create an RPSL object from a vector of slices parsed from RPSL text.
123impl From<Vec<(&str, Vec<&str>)>> for Object {
124 fn from(attribute_slices: Vec<(&str, Vec<&str>)>) -> Self {
125 let mut attributes: Vec<Attribute> = Vec::with_capacity(attribute_slices.len());
126
127 for attribute_slice in attribute_slices {
128 attributes.push(Attribute::from(attribute_slice));
129 }
130
131 Object(attributes)
132 }
133}
134///Represents a collection of RPSL objects, for example as the result of a whois query.
135#[derive(Debug, PartialEq, Eq)]
136pub struct ObjectCollection(Vec<Object>);
137
138impl ObjectCollection {
139 /// Create a new RPSL object collection from a vector of objects.
140 #[must_use]
141 pub fn new(objects: Vec<Object>) -> Self {
142 ObjectCollection(objects)
143 }
144}
145
146impl Index<usize> for ObjectCollection {
147 type Output = Object;
148
149 fn index(&self, index: usize) -> &Self::Output {
150 &self.0[index]
151 }
152}
153
154impl IntoIterator for ObjectCollection {
155 type Item = Object;
156 type IntoIter = std::vec::IntoIter<Object>;
157
158 fn into_iter(self) -> Self::IntoIter {
159 self.0.into_iter()
160 }
161}
162
163// Create an RPSL object collection from a vector of slices parsed from RPSL text.
164impl From<Vec<Vec<(&str, Vec<&str>)>>> for ObjectCollection {
165 fn from(object_slices: Vec<Vec<(&str, Vec<&str>)>>) -> Self {
166 let mut objects: Vec<Object> = Vec::with_capacity(object_slices.len());
167
168 for object in object_slices {
169 objects.push(Object::from(object));
170 }
171
172 ObjectCollection(objects)
173 }
174}