forensic_rs/field/
mod.rs

1use std::{borrow::Cow, path::PathBuf};
2
3use serde::{de::Visitor, Deserializer};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7pub(crate) mod internal;
8pub mod ip;
9pub mod utils;
10
11pub use ip::Ip;
12
13use crate::utils::time::Filetime;
14
15pub type Text = Cow<'static, str>;
16
17#[derive(Clone, Default)]
18#[non_exhaustive]
19pub enum Field {
20    #[default]
21    Null,
22    /// A basic String field
23    Text(Text),
24    /// IPv4 or IPv6
25    Ip(Ip),
26    //Domain like contoso.com
27    Domain(String),
28    User(String),
29    ///This is a special field. Uniquely identifies an asset like a system, a
30    /// computer or a mobile phone. Reason: the network is dynamic, the IP address
31    /// is not fixed certain devices and the hostname of a system can be changed.
32    ///
33    /// This field should be used with a dataset to recover information about an asset
34    /// during the enchance phase:
35    /// Getting the IP address, the users logged in the system or another information.
36    ///
37    /// Can be multiple AssetsID associated with the same event because multiple virtual
38    /// machines can be running in the same asset.
39    AssetID(String),
40    /// unsigned number with 64 bits
41    U64(u64),
42    /// signed number with 64 bits
43    I64(i64),
44    /// decimal number with 64 bits
45    F64(f64),
46    ///A date in a decimal number format with 64 bits
47    Date(Filetime),
48    Array(Vec<Text>),
49    Path(PathBuf),
50}
51
52impl std::fmt::Debug for Field {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        match self {
55            Self::Null => write!(f, "Null"),
56            Self::Text(arg0) => f.write_fmt(format_args!("{:?}", arg0)),
57            Self::Ip(arg0) => f.write_fmt(format_args!("{}", arg0)),
58            Self::Domain(arg0) => f.write_fmt(format_args!("{:?}", arg0)),
59            Self::User(arg0) => f.write_fmt(format_args!("{:?}", arg0)),
60            Self::AssetID(arg0) => f.write_fmt(format_args!("{:?}", arg0)),
61            Self::U64(arg0) => f.write_fmt(format_args!("{}", arg0)),
62            Self::I64(arg0) => f.write_fmt(format_args!("{}", arg0)),
63            Self::F64(arg0) => f.write_fmt(format_args!("{}", arg0)),
64            Self::Date(arg0) => f.write_fmt(format_args!("{:?}", arg0)),
65            Self::Array(arg0) => f.debug_list().entries(arg0.iter()).finish(),
66            Self::Path(arg0) => f.write_fmt(format_args!("{:?}", arg0.to_string_lossy())),
67        }
68    }
69}
70
71impl<'a> TryInto<&'a str> for &'a Field {
72    type Error = &'static str;
73
74    fn try_into(self) -> Result<&'a str, Self::Error> {
75        match self {
76            Field::Text(v) => Ok(&v[..]),
77            Field::Domain(v) => Ok(&v[..]),
78            Field::User(v) => Ok(&v[..]),
79            Field::AssetID(v) => Ok(&v[..]),
80            _ => Err("Invalid text type"),
81        }
82    }
83}
84
85impl<'a> TryInto<Text> for &'a Field {
86    type Error = &'static str;
87
88    fn try_into(self) -> Result<Text, Self::Error> {
89        match self {
90            Field::Text(v) => Ok(v.clone()),
91            Field::Domain(v) => Ok(Text::Owned(v.to_string())),
92            Field::User(v) => Ok(Text::Owned(v.to_string())),
93            Field::AssetID(v) => Ok(Text::Owned(v.to_string())),
94            _ => Err("Invalid type"),
95        }
96    }
97}
98impl<'a> TryInto<&'a Text> for &'a Field {
99    type Error = &'static str;
100
101    fn try_into(self) -> Result<&'a Text, Self::Error> {
102        match self {
103            Field::Text(v) => Ok(v),
104            _ => Err("Invalid type"),
105        }
106    }
107}
108
109impl<'a> TryInto<&'a Vec<Text>> for &'a Field {
110    type Error = &'static str;
111
112    fn try_into(self) -> Result<&'a Vec<Text>, Self::Error> {
113        match self {
114            Field::Array(v) => Ok(v),
115            _ => Err("Invalid type"),
116        }
117    }
118}
119
120impl<'a> TryInto<Vec<Text>> for &'a Field {
121    type Error = &'static str;
122
123    fn try_into(self) -> Result<Vec<Text>, Self::Error> {
124        let value = match self {
125            Field::Array(v) => return Ok(v.clone()),
126            Field::AssetID(v) => Text::Owned(v.clone()),
127            Field::Text(v) => v.clone(),
128            Field::Domain(v) => Text::Owned(v.clone()),
129            Field::User(v) => Text::Owned(v.clone()),
130            Field::I64(v) => Text::Owned(v.to_string()),
131            Field::F64(v) => Text::Owned(v.to_string()),
132            Field::U64(v) => Text::Owned(v.to_string()),
133            Field::Date(v) => Text::Owned(v.to_string()),
134            Field::Ip(v) => Text::Owned(v.to_string()),
135            Field::Null => Text::Borrowed(""),
136            Field::Path(v) => Text::Owned(v.to_string_lossy().to_string()),
137        };
138        Ok(vec![value])
139    }
140}
141
142impl<'a> TryInto<u64> for &'a Field {
143    type Error = &'static str;
144
145    fn try_into(self) -> Result<u64, Self::Error> {
146        Ok(match self {
147            Field::F64(v) => *v as u64,
148            Field::I64(v) => *v as u64,
149            Field::U64(v) => *v,
150            Field::Date(v) => v.filetime(),
151            _ => return Err("Invalid type"),
152        })
153    }
154}
155impl<'a> TryInto<i64> for &'a Field {
156    type Error = &'static str;
157
158    fn try_into(self) -> Result<i64, Self::Error> {
159        Ok(match self {
160            Field::F64(v) => *v as i64,
161            Field::I64(v) => *v,
162            Field::U64(v) => *v as i64,
163            Field::Date(v) => v.filetime() as i64,
164            _ => return Err("Invalid type"),
165        })
166    }
167}
168impl<'a> TryInto<f64> for &'a Field {
169    type Error = &'static str;
170
171    fn try_into(self) -> Result<f64, Self::Error> {
172        Ok(match self {
173            Field::F64(v) => *v,
174            Field::I64(v) => *v as f64,
175            Field::U64(v) => *v as f64,
176            Field::Date(v) => v.filetime() as f64,
177            _ => return Err("Invalid type"),
178        })
179    }
180}
181
182impl<'a> TryInto<Ip> for &'a Field {
183    type Error = &'static str;
184    fn try_into(self) -> Result<Ip, Self::Error> {
185        Ok(match self {
186            Field::Text(v) => Ip::from_ip_str(v).map_err(|_e| "Invalud ip format")?,
187            Field::Ip(v) => *v,
188            _ => return Err("Type cannot be converted to Ip"),
189        })
190    }
191}
192
193impl From<&'static str> for Field {
194    fn from(v: &'static str) -> Field {
195        Field::Text(Text::Borrowed(v))
196    }
197}
198impl From<&String> for Field {
199    fn from(v: &String) -> Field {
200        Field::Text(Text::Owned(v.to_string()))
201    }
202}
203impl From<String> for Field {
204    fn from(v: String) -> Field {
205        Field::Text(Text::Owned(v))
206    }
207}
208impl From<Text> for Field {
209    fn from(v: Text) -> Field {
210        Field::Text(v)
211    }
212}
213impl From<&Text> for Field {
214    fn from(v: &Text) -> Field {
215        Field::Text(v.clone())
216    }
217}
218
219impl From<&u64> for Field {
220    fn from(v: &u64) -> Field {
221        Field::U64(*v)
222    }
223}
224impl From<u64> for Field {
225    fn from(v: u64) -> Field {
226        Field::U64(v)
227    }
228}
229impl From<&u32> for Field {
230    fn from(v: &u32) -> Field {
231        Field::U64(*v as u64)
232    }
233}
234impl From<u32> for Field {
235    fn from(v: u32) -> Field {
236        Field::U64(v as u64)
237    }
238}
239
240impl From<&i64> for Field {
241    fn from(v: &i64) -> Field {
242        Field::I64(*v)
243    }
244}
245impl From<i64> for Field {
246    fn from(v: i64) -> Field {
247        Field::I64(v)
248    }
249}
250
251impl From<&f64> for Field {
252    fn from(v: &f64) -> Field {
253        Field::F64(*v)
254    }
255}
256impl From<f64> for Field {
257    fn from(v: f64) -> Field {
258        Field::F64(v)
259    }
260}
261impl From<Ip> for Field {
262    fn from(v: Ip) -> Field {
263        Field::Ip(v)
264    }
265}
266impl From<&Ip> for Field {
267    fn from(v: &Ip) -> Field {
268        Field::Ip(*v)
269    }
270}
271impl From<Vec<Text>> for Field {
272    fn from(v: Vec<Text>) -> Field {
273        Field::Array(v)
274    }
275}
276impl From<&Vec<Text>> for Field {
277    fn from(v: &Vec<Text>) -> Field {
278        Field::Array(v.clone())
279    }
280}
281
282#[cfg(feature = "serde")]
283impl Serialize for Field {
284    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
285    where
286        S: serde::Serializer,
287    {
288        match self {
289            Field::Null => serializer.serialize_none(),
290            Field::Text(v) => serializer.serialize_str(&v[..]),
291            Field::Ip(v) => v.serialize(serializer),
292            Field::Domain(v) => serializer.serialize_str(&v[..]),
293            Field::User(v) => serializer.serialize_str(&v[..]),
294            Field::AssetID(v) => serializer.serialize_str(&v[..]),
295            Field::U64(v) => serializer.serialize_u64(*v),
296            Field::I64(v) => serializer.serialize_i64(*v),
297            Field::F64(v) => serializer.serialize_f64(*v),
298            Field::Date(v) => serializer.serialize_str(&v.to_string()),
299            Field::Array(v) => v.serialize(serializer),
300            Field::Path(v) => serializer.serialize_str(&v.to_string_lossy()[..]),
301        }
302    }
303}
304#[cfg(feature = "serde")]
305impl<'de> Deserialize<'de> for Field {
306    fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
307    where
308        D: Deserializer<'de>,
309    {
310        deserializer.deserialize_any(FieldVisitor)
311    }
312}
313#[cfg(feature = "serde")]
314struct FieldVisitor;
315#[cfg(feature = "serde")]
316impl<'de> Visitor<'de> for FieldVisitor {
317    type Value = Field;
318
319    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
320        formatter.write_str("a valid forensic data")
321    }
322
323    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
324    where
325        E: serde::de::Error,
326    {
327        Ok(Field::Text(Cow::Owned(v.to_string())))
328    }
329    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
330    where
331        E: serde::de::Error,
332    {
333        Ok(Field::Text(Cow::Owned(v)))
334    }
335    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
336    where
337        E: serde::de::Error,
338    {
339        Ok(Field::U64(if v { 1 } else { 0 }))
340    }
341
342    fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
343    where
344        E: serde::de::Error,
345    {
346        Ok(Field::I64(v as _))
347    }
348    fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
349    where
350        E: serde::de::Error,
351    {
352        Ok(Field::I64(v as _))
353    }
354    fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
355    where
356        E: serde::de::Error,
357    {
358        Ok(Field::I64(v as _))
359    }
360    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
361    where
362        E: serde::de::Error,
363    {
364        Ok(Field::I64(v))
365    }
366    fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
367    where
368        E: serde::de::Error,
369    {
370        Ok(Field::F64(v as _))
371    }
372
373    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
374    where
375        E: serde::de::Error,
376    {
377        Ok(Field::F64(v))
378    }
379
380    fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
381    where
382        E: serde::de::Error,
383    {
384        Ok(Field::U64(v as _))
385    }
386    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
387    where
388        E: serde::de::Error,
389    {
390        Ok(Field::U64(v))
391    }
392
393    fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
394    where
395        E: serde::de::Error,
396    {
397        Ok(Field::U64(v as _))
398    }
399    fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
400    where
401        E: serde::de::Error,
402    {
403        Ok(Field::U64(v as _))
404    }
405    fn visit_unit<E>(self) -> Result<Self::Value, E>
406        where
407            E: serde::de::Error, {
408        Ok(Field::Null)
409    }
410    fn visit_none<E>(self) -> Result<Self::Value, E>
411        where
412            E: serde::de::Error, {
413        Ok(Field::Null)
414    }
415
416    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
417        where
418            A: serde::de::SeqAccess<'de>, {
419        let mut vc = Vec::with_capacity(32);
420        while let Some(value) = seq.next_element()? {
421            vc.push(value);
422        }
423        Ok(Field::Array(vc))
424    }
425}