1use std::fmt;
2#[cfg(feature = "serde-1")]
3use std::str::FromStr;
4
5#[cfg(feature = "serde-1")]
6use serde::{
7 de::{self, Visitor},
8 Deserialize, Deserializer, Serialize, Serializer,
9};
10pub use uuid;
11use uuid::Uuid;
12
13pub mod importer_context;
14pub mod utils;
15
16#[derive(PartialEq, Eq, Clone, Copy, Default, Hash, Ord, PartialOrd)]
23pub struct AssetUuid(pub [u8; 16]);
24
25impl<S: AsRef<str>> From<S> for AssetUuid {
26 fn from(s: S) -> Self {
27 AssetUuid(
28 *Uuid::parse_str(s.as_ref())
29 .expect("Macro input is not a UUID string")
30 .as_bytes(),
31 )
32 }
33}
34
35impl AsMut<[u8]> for AssetUuid {
36 fn as_mut(&mut self) -> &mut [u8] {
37 &mut self.0
38 }
39}
40
41impl AsRef<[u8]> for AssetUuid {
42 fn as_ref(&self) -> &[u8] {
43 &self.0
44 }
45}
46
47impl fmt::Debug for AssetUuid {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 f.debug_tuple("AssetUuid")
50 .field(&uuid::Uuid::from_bytes(self.0))
51 .finish()
52 }
53}
54
55impl fmt::Display for AssetUuid {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 uuid::Uuid::from_bytes(self.0).fmt(f)
58 }
59}
60
61#[cfg(feature = "serde-1")]
62impl Serialize for AssetUuid {
63 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
64 if serializer.is_human_readable() {
65 serializer.serialize_str(&self.to_string())
66 } else {
67 self.0.serialize(serializer)
68 }
69 }
70}
71
72#[cfg(feature = "serde-1")]
73struct AssetUuidVisitor;
74
75#[cfg(feature = "serde-1")]
76impl<'a> Visitor<'a> for AssetUuidVisitor {
77 type Value = AssetUuid;
78
79 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
80 write!(fmt, "a UUID-formatted string")
81 }
82
83 fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
84 uuid::Uuid::from_str(s)
85 .map(|id| AssetUuid(*id.as_bytes()))
86 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))
87 }
88}
89
90#[cfg(feature = "serde-1")]
91impl<'de> Deserialize<'de> for AssetUuid {
92 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
93 if deserializer.is_human_readable() {
94 deserializer.deserialize_string(AssetUuidVisitor)
95 } else {
96 Ok(AssetUuid(<[u8; 16]>::deserialize(deserializer)?))
97 }
98 }
99}
100
101#[derive(PartialEq, Eq, Debug, Clone, Copy, Default, Hash)]
106pub struct AssetTypeId(pub [u8; 16]);
107
108impl AsMut<[u8]> for AssetTypeId {
109 fn as_mut(&mut self) -> &mut [u8] {
110 &mut self.0
111 }
112}
113
114impl AsRef<[u8]> for AssetTypeId {
115 fn as_ref(&self) -> &[u8] {
116 &self.0
117 }
118}
119
120impl fmt::Display for AssetTypeId {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 uuid::Uuid::from_bytes(self.0).fmt(f)
123 }
124}
125
126#[cfg(feature = "serde-1")]
127impl Serialize for AssetTypeId {
128 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
129 if serializer.is_human_readable() {
130 serializer.serialize_str(&self.to_string())
131 } else {
132 self.0.serialize(serializer)
133 }
134 }
135}
136
137#[cfg(feature = "serde-1")]
138struct AssetTypeIdVisitor;
139
140#[cfg(feature = "serde-1")]
141impl<'a> Visitor<'a> for AssetTypeIdVisitor {
142 type Value = AssetTypeId;
143
144 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
145 write!(fmt, "a UUID-formatted string")
146 }
147
148 fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
149 uuid::Uuid::parse_str(s)
150 .map(|id| AssetTypeId(*id.as_bytes()))
151 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))
152 }
153}
154
155#[cfg(feature = "serde-1")]
156impl<'de> Deserialize<'de> for AssetTypeId {
157 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
158 if deserializer.is_human_readable() {
159 deserializer.deserialize_string(AssetTypeIdVisitor)
160 } else {
161 Ok(AssetTypeId(<[u8; 16]>::deserialize(deserializer)?))
162 }
163 }
164}
165
166#[derive(Debug, Hash, PartialEq, Eq, Clone, Ord, PartialOrd)]
168#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
169pub enum AssetRef {
170 Uuid(AssetUuid),
171 Path(std::path::PathBuf),
172}
173impl AssetRef {
174 pub fn expect_uuid(&self) -> &AssetUuid {
175 if let AssetRef::Uuid(uuid) = self {
176 uuid
177 } else {
178 panic!("Expected AssetRef::Uuid, got {:?}", self)
179 }
180 }
181
182 pub fn is_path(&self) -> bool {
183 matches!(self, AssetRef::Path(_))
184 }
185
186 pub fn is_uuid(&self) -> bool {
187 matches!(self, AssetRef::Uuid(_))
188 }
189}
190
191#[derive(Debug, Hash, PartialEq, Copy, Clone)]
192#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
193pub enum CompressionType {
194 None,
195 Lz4,
196}
197
198impl Default for CompressionType {
199 fn default() -> Self {
200 Self::None
201 }
202}
203
204#[derive(Debug, Clone, Hash, Default)]
207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
208pub struct AssetMetadata {
209 pub id: AssetUuid,
211 pub search_tags: Vec<(String, Option<String>)>,
213 pub build_pipeline: Option<AssetUuid>,
215 pub artifact: Option<ArtifactMetadata>,
217}
218
219#[derive(Debug, Copy, Clone, Hash, Default)]
221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
222#[cfg_attr(feature = "serde", serde(transparent))]
223pub struct ArtifactId(pub u64);
224
225#[derive(Debug, Clone, Hash, Default)]
228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
229pub struct ArtifactMetadata {
230 pub id: ArtifactId,
232 pub asset_id: AssetUuid,
234 pub build_deps: Vec<AssetRef>,
236 pub load_deps: Vec<AssetRef>,
238 pub compression: CompressionType,
240 pub compressed_size: Option<u64>,
242 pub uncompressed_size: Option<u64>,
244 pub type_id: AssetTypeId,
246}
247
248pub trait TypeUuidDynamic {
250 fn uuid(&self) -> [u8; 16];
251}
252
253#[cfg(feature = "type_uuid")]
254impl<T: type_uuid::TypeUuidDynamic> TypeUuidDynamic for T {
255 fn uuid(&self) -> [u8; 16] {
256 <Self as type_uuid::TypeUuidDynamic>::uuid(self)
257 }
258}
259
260#[cfg(feature = "type_uuid")]
261pub use type_uuid;