nuit_core/utils/
identified.rs

1use serde::{Serialize, Deserialize};
2
3use crate::Id;
4
5/// A value with an id.
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "camelCase")]
8pub struct Identified<T> {
9    id: Id,
10    value: T,
11}
12
13impl<T> Identified<T> {
14    /// Creates a new `Identified<T>` identifying the given value with the given id.
15    pub fn new(id: &Id, value: T) -> Self {
16        Self { id: id.clone(), value }
17    }
18
19    /// The id.
20    pub const fn id(&self) -> &Id {
21        &self.id
22    }
23
24    /// The wrapped value.
25    pub const fn value(&self) -> &T {
26        &self.value
27    }
28
29    /// Consumes and returns the value.
30    pub fn into_value(self) -> T {
31        self.value
32    }
33
34    /// Converts from an `&Identified<T>` to an `Identified<&T>`. Note that
35    /// this involves cloning the id, which may be undesirable if expensive.
36    pub fn as_ref(&self) -> Identified<&T> {
37        Identified { id: self.id.clone(), value: &self.value }
38    }
39
40    /// Maps the given function over the value.
41    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Identified<U> {
42        Identified { id: self.id, value: f(self.value) }
43    }
44
45    /// Maps the given function over the value, providing the id.
46    pub fn map_with_id<U>(self, f: impl FnOnce(&Id, T) -> U) -> Identified<U> {
47        let value = f(&self.id, self.value);
48        Identified { id: self.id, value }
49    }
50}
51
52/// An extension trait for conveniently creating `Identified` values.
53pub trait IdentifyExt where Self: Sized {
54    fn identify(self, id: impl Into<Id>) -> Identified<Self>;
55}
56
57impl<T> IdentifyExt for T {
58    fn identify(self, id: impl Into<Id>) -> Identified<Self> {
59        Identified { id: id.into(), value: self }
60    }
61}