1use serde::{de, ser};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use std::str::FromStr;
5use uuid::Uuid;
6
7#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Default)]
10pub struct AssetId(pub Uuid);
11impl AssetId {
12 pub const fn null() -> Self {
13 AssetId(Uuid::nil())
14 }
15
16 pub fn parse_str(input: &str) -> Result<Self, uuid::Error> {
17 Ok(AssetId(Uuid::parse_str(input)?))
18 }
19
20 pub fn is_null(&self) -> bool {
21 self.0.is_nil()
22 }
23
24 pub fn from_uuid(uuid: Uuid) -> Self {
25 AssetId(uuid)
26 }
27
28 pub fn as_uuid(&self) -> Uuid {
29 self.0
30 }
31
32 pub fn from_u128(u: u128) -> Self {
33 Self(Uuid::from_u128(u))
34 }
35
36 pub fn as_u128(&self) -> u128 {
37 self.0.as_u128()
38 }
39
40 pub fn from_bytes(bytes: uuid::Bytes) -> Self {
41 AssetId(Uuid::from_bytes(bytes))
42 }
43
44 pub fn as_bytes(&self) -> &uuid::Bytes {
45 self.0.as_bytes()
46 }
47}
48
49impl fmt::Debug for AssetId {
50 fn fmt(
51 &self,
52 f: &mut fmt::Formatter<'_>,
53 ) -> fmt::Result {
54 f.debug_tuple("AssetId").field(&self.0).finish()
55 }
56}
57
58impl fmt::Display for AssetId {
59 fn fmt(
60 &self,
61 f: &mut fmt::Formatter<'_>,
62 ) -> fmt::Result {
63 self.0.fmt(f)
64 }
65}
66
67impl Serialize for AssetId {
68 fn serialize<S: ser::Serializer>(
69 &self,
70 serializer: S,
71 ) -> Result<S::Ok, S::Error> {
72 if serializer.is_human_readable() {
73 serializer.serialize_str(&self.to_string())
74 } else {
75 self.0.serialize(serializer)
76 }
77 }
78}
79
80struct AssetIdVisitor;
81
82impl<'a> de::Visitor<'a> for AssetIdVisitor {
83 type Value = AssetId;
84
85 fn expecting(
86 &self,
87 fmt: &mut fmt::Formatter<'_>,
88 ) -> fmt::Result {
89 write!(fmt, "a UUID-formatted string")
90 }
91
92 fn visit_str<E: de::Error>(
93 self,
94 s: &str,
95 ) -> Result<Self::Value, E> {
96 Uuid::from_str(s)
97 .map(|id| AssetId(id))
98 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))
99 }
100}
101
102impl<'de> Deserialize<'de> for AssetId {
103 fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
104 if deserializer.is_human_readable() {
105 deserializer.deserialize_string(AssetIdVisitor)
106 } else {
107 Ok(AssetId(Uuid::deserialize(deserializer)?))
108 }
109 }
110}