1use std::cmp::Ordering;
2use std::fmt::{self, Debug, Display};
3use std::hash::{self, Hash};
4use std::marker::PhantomData;
5use std::str::FromStr;
6
7use chrono::{DateTime, Utc};
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9use thiserror::Error;
10
11pub mod aid;
12pub mod meid;
13pub mod object_id;
14
15#[cfg(feature = "aid")]
16type IdImpl = aid::Aid;
17#[cfg(feature = "meid")]
18type IdImpl = meid::Meid;
19#[cfg(feature = "ulid")]
20type IdImpl = ulid_crate::Ulid;
21#[cfg(feature = "objectid")]
22type IdImpl = object_id::ObjectId;
23
24pub struct Id<T: ?Sized> {
25 inner: IdImpl,
26 _marker: PhantomData<fn() -> T>,
27}
28
29impl<T: ?Sized> Id<T> {
30 #[cfg(any(docsrs, feature = "aid"))]
31 #[cfg_attr(docsrs, doc(cfg(feature = "aid")))]
32 pub fn as_aid(&self) -> &aid::Aid {
33 &self.inner
34 }
35
36 #[cfg(any(docsrs, feature = "meid"))]
37 #[cfg_attr(docsrs, doc(cfg(feature = "meid")))]
38 pub fn as_meid(&self) -> &meid::Meid {
39 &self.inner
40 }
41
42 #[cfg(any(docsrs, feature = "ulid"))]
43 #[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
44 pub fn as_ulid(&self) -> &ulid_crate::Ulid {
45 &self.inner
46 }
47
48 #[cfg(any(docsrs, feature = "objectid"))]
49 #[cfg_attr(docsrs, doc(cfg(feature = "objectid")))]
50 pub fn as_object_id(&self) -> &object_id::ObjectId {
51 &self.inner
52 }
53}
54
55#[cfg(feature = "aid")]
56impl<T: ?Sized> From<Id<T>> for aid::Aid {
57 fn from(id: Id<T>) -> aid::Aid {
58 *id.as_aid()
59 }
60}
61
62#[cfg(feature = "meid")]
63impl<T: ?Sized> From<Id<T>> for meid::Meid {
64 fn from(id: Id<T>) -> meid::Meid {
65 *id.as_meid()
66 }
67}
68
69#[cfg(feature = "ulid")]
70impl<T: ?Sized> From<Id<T>> for ulid_crate::Ulid {
71 fn from(id: Id<T>) -> ulid_crate::Ulid {
72 *id.as_ulid()
73 }
74}
75
76#[cfg(feature = "objectid")]
77impl<T: ?Sized> From<Id<T>> for object_id::ObjectId {
78 fn from(id: Id<T>) -> object_id::ObjectId {
79 *id.as_object_id()
80 }
81}
82
83impl<T> Debug for Id<T> {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 Debug::fmt(&self.inner, f)
89 }
90}
91
92impl<T> PartialOrd for Id<T> {
93 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
94 self.inner.partial_cmp(&other.inner)
95 }
96}
97
98impl<T> Ord for Id<T> {
99 fn cmp(&self, other: &Self) -> Ordering {
100 self.inner.cmp(&other.inner)
101 }
102}
103
104impl<T> PartialEq for Id<T> {
105 fn eq(&self, other: &Self) -> bool {
106 self.inner.eq(&other.inner)
107 }
108}
109
110impl<T> Eq for Id<T> {}
111
112impl<T> Clone for Id<T> {
113 fn clone(&self) -> Self {
114 Id {
115 inner: self.inner,
116 _marker: PhantomData,
117 }
118 }
119}
120
121impl<T> Copy for Id<T> {}
122
123impl<T> Hash for Id<T> {
124 fn hash<H>(&self, state: &mut H)
125 where
126 H: hash::Hasher,
127 {
128 self.inner.hash(state);
129 }
130}
131
132impl<T> Id<T> {
133 pub fn datetime(&self) -> DateTime<Utc> {
134 self.inner.datetime()
135 }
136}
137
138#[derive(Debug, Error, Clone)]
139#[error("invalid id")]
140pub struct ParseIdError {
141 _priv: (),
142}
143
144impl<T> FromStr for Id<T> {
145 type Err = ParseIdError;
146
147 fn from_str(s: &str) -> Result<Id<T>, Self::Err> {
148 IdImpl::from_str(s)
149 .map(|inner| Id {
150 inner,
151 _marker: PhantomData,
152 })
153 .map_err(|_| ParseIdError { _priv: () })
154 }
155}
156
157impl<T> Display for Id<T> {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 Display::fmt(&self.inner, f)
160 }
161}
162
163impl<T> Serialize for Id<T> {
164 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
165 where
166 S: Serializer,
167 {
168 self.inner.serialize(serializer)
169 }
170}
171
172impl<'de, T> Deserialize<'de> for Id<T> {
173 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
174 where
175 D: Deserializer<'de>,
176 {
177 IdImpl::deserialize(deserializer).map(|inner| Id {
178 inner,
179 _marker: PhantomData,
180 })
181 }
182}