apub_core/
object_id.rs

1//! A provided ObjectId type
2
3use std::{
4    borrow::Cow,
5    fmt::Display,
6    marker::PhantomData,
7    ops::{Deref, DerefMut},
8};
9use url::Url;
10
11/// A type generic over a `Kind` but contains only an internal Url
12///
13/// This type likely shouldn't be used directly, but is a helper for building your own ObjectId
14/// type.
15///
16/// ```rust
17/// use apub_core::repo::Dereference;
18/// use url::Url;
19///
20/// #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
21/// #[serde(transparent)]
22/// pub struct ObjectId<Kind>(apub_core::object_id::ObjectId<'static, Kind>);
23///
24/// pub fn object_id<Kind>(url: Url) -> ObjectId<Kind> {
25///     ObjectId(apub_core::object_id::ObjectId::new_owned(url))
26/// }
27///
28/// #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
29/// struct MyKind;
30/// #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
31/// struct MyObject {
32///     id: ObjectId<MyKind>,
33/// }
34///
35/// impl Dereference for ObjectId<MyKind> {
36///     type Output = MyObject;
37///
38///     fn url(&self) -> &Url {
39///         &self.0
40///     }
41/// }
42/// ```
43#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
44pub struct ObjectId<'a, Kind> {
45    url: Cow<'a, Url>,
46    _kind: PhantomData<fn() -> Kind>,
47}
48
49impl<'a, Kind> Clone for ObjectId<'a, Kind> {
50    fn clone(&self) -> Self {
51        Self {
52            url: self.url.clone(),
53            _kind: PhantomData,
54        }
55    }
56}
57
58impl<Kind> ObjectId<'static, Kind> {
59    /// Create a new owned ObjectId
60    pub fn new_owned(url: Url) -> Self {
61        Self {
62            url: Cow::Owned(url),
63            _kind: PhantomData,
64        }
65    }
66}
67
68impl<'a, Kind> ObjectId<'a, Kind> {
69    /// Create a new borrowed ObjectId
70    ///
71    /// This is useful for creating a valid Dereference type from a borrowed Url without cloning
72    pub fn new_borrowed(url: &'a Url) -> Self {
73        Self {
74            url: Cow::Borrowed(url),
75            _kind: PhantomData,
76        }
77    }
78}
79
80impl<'a, Kind> Deref for ObjectId<'a, Kind> {
81    type Target = Url;
82
83    fn deref(&self) -> &Self::Target {
84        &self.url
85    }
86}
87
88impl<'a, Kind> DerefMut for ObjectId<'a, Kind> {
89    fn deref_mut(&mut self) -> &mut Self::Target {
90        self.url.to_mut()
91    }
92}
93
94impl<'a, Kind> Display for ObjectId<'a, Kind> {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        self.url.fmt(f)
97    }
98}
99
100impl<'a, Kind> serde::ser::Serialize for ObjectId<'a, Kind> {
101    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102    where
103        S: serde::Serializer,
104    {
105        self.url.serialize(serializer)
106    }
107}
108
109impl<'de, Kind> serde::de::Deserialize<'de> for ObjectId<'static, Kind> {
110    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111    where
112        D: serde::Deserializer<'de>,
113    {
114        Url::deserialize(deserializer).map(ObjectId::new_owned)
115    }
116}