1use std::fmt;
2use std::hash::{Hash, Hasher};
3use std::marker::PhantomData;
4
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use sofie_core::{Cast, ColumnReader, ColumnSpec, Result, Show, Shown, SqlValue, Uuid};
7use sofie_values::{Input, Present};
8
9pub struct Id<A> {
10 uuid: Uuid,
11 aggregate: PhantomData<fn() -> A>,
12}
13
14impl<A> Id<A> {
15 #[must_use]
16 pub const fn from_uuid(uuid: Uuid) -> Self {
17 Self {
18 uuid,
19 aggregate: PhantomData,
20 }
21 }
22
23 #[must_use]
24 pub const fn uuid(self) -> Uuid {
25 self.uuid
26 }
27}
28
29impl<A> Clone for Id<A> {
30 fn clone(&self) -> Self {
31 *self
32 }
33}
34
35impl<A> Copy for Id<A> {}
36
37impl<A> sofie_core::Ordered for Id<A> {}
38
39impl<A> PartialEq for Id<A> {
40 fn eq(&self, other: &Self) -> bool {
41 self.uuid == other.uuid
42 }
43}
44
45impl<A> Eq for Id<A> {}
46
47impl<A> Hash for Id<A> {
48 fn hash<H: Hasher>(&self, state: &mut H) {
49 self.uuid.hash(state);
50 }
51}
52
53impl<A> fmt::Debug for Id<A> {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 fmt::Display::fmt(&self.uuid, f)
56 }
57}
58
59impl<A> fmt::Display for Id<A> {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 fmt::Display::fmt(&self.uuid, f)
62 }
63}
64
65impl<A> Cast for Id<A> {
66 const COLUMNS: &'static [ColumnSpec] = Uuid::COLUMNS;
67
68 fn encode(&self, out: &mut Vec<SqlValue>) {
69 self.uuid.encode(out);
70 }
71
72 fn decode(row: &mut dyn ColumnReader) -> Result<Self> {
73 Uuid::decode(row).map(Self::from_uuid)
74 }
75}
76
77impl<A> Show for Id<A> {
78 fn show(&self) -> Shown<'_> {
79 Shown::Uuid(self.uuid)
80 }
81}
82
83impl<A> Serialize for Id<A> {
84 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
85 serializer.collect_str(&self.uuid)
86 }
87}
88
89impl<'de, A> Deserialize<'de> for Id<A> {
90 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
91 Uuid::deserialize(deserializer).map(Self::from_uuid)
92 }
93}
94
95impl<A> Present for Id<A> {
96 const INPUT: Input = Uuid::INPUT;
97 const SEARCH: sofie_values::Search = Uuid::SEARCH;
98
99 fn csv(&self) -> String {
100 self.uuid.csv()
101 }
102}