openc2/
data.rs

1use std::{borrow::Borrow, fmt, str::FromStr};
2
3use indexmap::{IndexMap, IndexSet};
4use serde::{Deserialize, Serialize, de::Error as _};
5use serde_with::{DeserializeFromStr, SerializeDisplay, skip_serializing_none};
6use url::Url;
7
8use crate::{Action, IsEmpty, TargetType};
9
10mod ipnet;
11mod mac_addr;
12mod nsid;
13pub mod primitive;
14mod time;
15mod value;
16mod version;
17
18pub use ipnet::{Ipv4Net, Ipv6Net};
19pub use mac_addr::{MacAddr, MacAddr6, MacAddr8};
20pub use nsid::Nsid;
21pub use time::{DateTime, Duration};
22pub use value::Value;
23pub use version::Version;
24
25pub type ActionTargets = IndexMap<Action, IndexSet<TargetType<'static>>>;
26
27pub type CommandId = String;
28
29#[derive(
30    Debug, Clone, SerializeDisplay, DeserializeFromStr, PartialEq, Eq, PartialOrd, Ord, Hash,
31)]
32pub struct DomainName(String);
33
34impl fmt::Display for DomainName {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        self.0.fmt(f)
37    }
38}
39
40impl FromStr for DomainName {
41    type Err = crate::error::ValidationError;
42
43    fn from_str(s: &str) -> Result<Self, Self::Err> {
44        Ok(Self(s.to_string()))
45    }
46}
47
48#[derive(
49    Debug, Clone, SerializeDisplay, DeserializeFromStr, PartialEq, Eq, PartialOrd, Ord, Hash,
50)]
51pub struct EmailAddr(String);
52
53impl fmt::Display for EmailAddr {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        self.0.fmt(f)
56    }
57}
58
59impl FromStr for EmailAddr {
60    type Err = crate::error::ValidationError;
61
62    fn from_str(s: &str) -> Result<Self, Self::Err> {
63        Ok(Self(s.to_string()))
64    }
65}
66
67#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
68#[serde(transparent)]
69pub struct Extensions<V>(IndexMap<Nsid, V>);
70
71impl<V> Extensions<V> {
72    pub fn len(&self) -> usize {
73        self.0.len()
74    }
75
76    pub fn is_empty(&self) -> bool {
77        self.0.is_empty()
78    }
79
80    pub fn contains(&self, key: &impl Borrow<str>) -> bool {
81        self.0.contains_key(key.borrow())
82    }
83
84    pub fn get_raw(&self, key: &impl Borrow<str>) -> Option<&V> {
85        self.0.get(key.borrow())
86    }
87
88    pub fn insert(&mut self, key: Nsid, value: V) -> Option<V> {
89        self.0.insert(key, value)
90    }
91}
92
93impl<V: Value + Clone> Extensions<V> {
94    /// Gets an extension's value by key, or returns `None` if the key doesn't exist.
95    pub fn get<'de, T: Deserialize<'de>>(
96        &'de self,
97        key: &impl Borrow<str>,
98    ) -> Option<Result<T, V::Error>> {
99        self.get_raw(key).map(|v| v.to_typed())
100    }
101
102    /// Get's an extension's value by key, returning an error if the key doesn't exist or
103    /// doesn't deserialize into the provided type.
104    pub fn require<'de, T: Deserialize<'de>>(
105        &'de self,
106        key: &impl Borrow<str>,
107    ) -> Result<T, V::Error> {
108        self.get::<T>(key)
109            .transpose()?
110            .ok_or_else(|| V::Error::custom(format!("extension {} is required", key.borrow())))
111    }
112}
113
114impl<V> Default for Extensions<V> {
115    fn default() -> Self {
116        Self(Default::default())
117    }
118}
119
120impl<V> IsEmpty for Extensions<V> {
121    fn is_empty(&self) -> bool {
122        self.0.is_empty()
123    }
124}
125
126impl<'de, V: Deserialize<'de>> Deserialize<'de> for Extensions<V> {
127    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
128    where
129        D: serde::Deserializer<'de>,
130    {
131        let map = IndexMap::<Nsid, V>::deserialize(deserializer)?;
132        Ok(Self(map))
133    }
134}
135
136impl<V> IntoIterator for Extensions<V> {
137    type Item = (Nsid, V);
138    type IntoIter = indexmap::map::IntoIter<Nsid, V>;
139
140    fn into_iter(self) -> Self::IntoIter {
141        self.0.into_iter()
142    }
143}
144
145impl<'a, V> IntoIterator for &'a Extensions<V> {
146    type Item = (&'a Nsid, &'a V);
147    type IntoIter = indexmap::map::Iter<'a, Nsid, V>;
148
149    fn into_iter(self) -> Self::IntoIter {
150        self.0.iter()
151    }
152}
153
154impl<V> FromIterator<(Nsid, V)> for Extensions<V> {
155    fn from_iter<T: IntoIterator<Item = (Nsid, V)>>(iter: T) -> Self {
156        Self(iter.into_iter().collect())
157    }
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
161#[serde(rename_all = "snake_case")]
162#[non_exhaustive]
163pub enum Feature {
164    Versions,
165    Profiles,
166    Pairs,
167    RateLimit,
168}
169
170#[skip_serializing_none]
171#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash)]
172pub struct Hashes {
173    pub md5: Option<String>,
174    pub sha1: Option<String>,
175    pub sha256: Option<String>,
176}
177
178impl IsEmpty for Hashes {
179    fn is_empty(&self) -> bool {
180        self.md5.is_none() && self.sha1.is_none() && self.sha256.is_none()
181    }
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
185#[serde(rename_all = "snake_case")]
186pub enum Payload {
187    #[serde(rename = "bin")]
188    Binary(Vec<u8>),
189    Url(Url),
190}
191
192pub type Port = u16;
193
194#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
195#[serde(rename_all = "snake_case")]
196pub enum ResponseType {
197    None,
198    Ack,
199    Status,
200    Complete,
201}
202
203impl ResponseType {
204    pub fn requires_request_id(self) -> bool {
205        !matches!(self, ResponseType::None)
206    }
207}