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}