1use crate::SerializableFormat;
10use serde::{
11 de::{self, DeserializeSeed, Expected, SeqAccess, Visitor},
12 ser::{Serialize, SerializeTupleStruct, Serializer},
13 Deserialize, Deserializer,
14};
15use std::{collections::BTreeMap, marker::PhantomData};
16
17pub trait FormatRegisteredData: 'static {
41 #[doc(hidden)]
43 type Registration;
44 #[doc(hidden)]
45 fn get_registration(
46 name: &'static str,
47 deserializer: DeserializeFn<dyn SerializableFormat<Self>>,
48 ) -> Self::Registration;
49 #[doc(hidden)]
50 fn registry() -> &'static Registry<dyn SerializableFormat<Self>>;
51}
52
53#[doc(hidden)]
55pub type DeserializeFn<T> =
56 fn(&mut dyn erased_serde::Deserializer<'_>) -> erased_serde::Result<Box<T>>;
57
58#[doc(hidden)]
60pub struct Registry<T: ?Sized> {
61 pub map: BTreeMap<&'static str, Option<DeserializeFn<T>>>,
62 pub names: Vec<&'static str>,
63}
64
65pub struct SeqLookupVisitor<'a, T: ?Sized + 'static> {
66 pub expected: &'a dyn Expected,
67 pub registry: &'static Registry<T>,
68}
69
70impl<'de, 'a, T: ?Sized + 'static> Visitor<'de> for SeqLookupVisitor<'a, T> {
71 type Value = DeserializeFn<T>;
72
73 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 Expected::fmt(self.expected, formatter)
75 }
76
77 fn visit_str<E: de::Error>(self, key: &str) -> Result<Self::Value, E> {
78 match self.registry.map.get(key) {
79 Some(Some(value)) => Ok(*value),
80 Some(None) => Err(de::Error::custom(format_args!(
81 "non-unique tag of {}: {:?}",
82 self.expected, key
83 ))),
84 None => Err(de::Error::unknown_variant(key, &self.registry.names)),
85 }
86 }
87}
88
89impl<'de, 'a, T: ?Sized + 'static> DeserializeSeed<'de> for SeqLookupVisitor<'a, T> {
90 type Value = DeserializeFn<T>;
91 fn deserialize<D: Deserializer<'de>>(self, de: D) -> Result<Self::Value, D::Error> {
92 de.deserialize_str(self)
93 }
94}
95
96struct FnApply<T: ?Sized> {
97 pub deserialize_fn: DeserializeFn<T>,
98}
99
100impl<'de, T: ?Sized> DeserializeSeed<'de> for FnApply<T> {
101 type Value = Box<T>;
102
103 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
104 where
105 D: Deserializer<'de>,
106 {
107 let mut erased = erased_serde::Deserializer::erase(deserializer);
108 (self.deserialize_fn)(&mut erased).map_err(de::Error::custom)
109 }
110}
111
112struct FormatVisitor<D: FormatRegisteredData>(PhantomData<D>);
113
114impl<'de, D: FormatRegisteredData> Visitor<'de> for FormatVisitor<D> {
115 type Value = Box<dyn SerializableFormat<D>>;
116
117 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 write!(formatter, "dyn SerializableFormat")
119 }
120
121 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
122 where
123 A: SeqAccess<'de>,
124 {
125 let seq_lookup = SeqLookupVisitor {
126 expected: &self,
127 registry: <D as FormatRegisteredData>::registry(),
128 };
129 let deserialize_fn = match seq.next_element_seed(seq_lookup)? {
130 Some(deserialize_fn) => deserialize_fn,
131 None => {
132 return Err(de::Error::custom("expected tagged Format"));
133 }
134 };
135 seq.next_element_seed(FnApply { deserialize_fn })?
136 .ok_or_else(|| de::Error::invalid_length(1, &self))
137 }
138}
139
140impl<D: FormatRegisteredData> Serialize for dyn SerializableFormat<D> {
141 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
142 let mut ser = serializer.serialize_tuple_struct("Format", 2)?;
143 ser.serialize_field(self.name())?;
144 ser.serialize_field(&SerializableFormatWrapper(self))?;
145 ser.end()
146 }
147}
148
149struct SerializableFormatWrapper<'a, T: ?Sized>(pub &'a T);
150
151impl<'a, T> Serialize for SerializableFormatWrapper<'a, T>
152where
153 T: ?Sized + erased_serde::Serialize + 'a,
154{
155 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
156 where
157 S: Serializer,
158 {
159 erased_serde::serialize(self.0, serializer)
160 }
161}
162
163impl<'de, D: FormatRegisteredData> Deserialize<'de> for Box<dyn SerializableFormat<D>> {
164 fn deserialize<DE: Deserializer<'de>>(
165 deserializer: DE,
166 ) -> std::result::Result<Self, DE::Error> {
167 deserializer.deserialize_tuple_struct("Format", 2, FormatVisitor::<D>(PhantomData))
168 }
169}
170
171impl<D: FormatRegisteredData> dyn SerializableFormat<D> {
172 #[doc(hidden)]
174 pub fn format_register(
175 name: &'static str,
176 deserializer: DeserializeFn<Self>,
177 ) -> D::Registration {
178 D::get_registration(name, deserializer)
179 }
180}
181
182#[macro_export]
187macro_rules! register_format_type {
188 ($($asset_data:ty),*) => {
189 $(
190 #[allow(non_upper_case_globals)]
191 const _register_format_type_impl: () = {
192 $crate::inventory::collect!(AssetFormatRegistration);
193
194 #[doc(hidden)]
195 #[allow(unused)]
196 pub struct AssetFormatRegistration {
197 name: &'static str,
198 deserializer: $crate::DeserializeFn<dyn $crate::SerializableFormat<$asset_data>>,
199 }
200
201 impl $crate::FormatRegisteredData for $asset_data {
202 type Registration = AssetFormatRegistration;
203 fn get_registration(name: &'static str, deserializer: $crate::DeserializeFn<dyn $crate::SerializableFormat<Self>>) -> Self::Registration {
204 AssetFormatRegistration { name, deserializer }
205 }
206 fn registry() -> &'static $crate::Registry<dyn $crate::SerializableFormat<Self>> {
207 ®ISTRY
208 }
209 }
210
211 $crate::lazy_static::lazy_static! {
212 static ref REGISTRY: $crate::Registry<dyn $crate::SerializableFormat<$asset_data>> = {
213 let mut map = std::collections::BTreeMap::new();
214 let mut names = std::vec::Vec::new();
215 for registered in $crate::inventory::iter::<AssetFormatRegistration> {
216 match map.entry(registered.name) {
217 std::collections::btree_map::Entry::Vacant(entry) => {
218 entry.insert(std::option::Option::Some(registered.deserializer));
219 }
220 std::collections::btree_map::Entry::Occupied(mut entry) => {
221 entry.insert(std::option::Option::None);
222 }
223 }
224 names.push(registered.name);
225 }
226 names.sort_unstable();
227 $crate::Registry { map, names }
228 };
229 }
230 };
231 )*
232 }
233}
234
235#[macro_export]
253macro_rules! register_format {
254 ($name:literal, $format:ty as $data:ty) => {
255 $crate::register_format!(amethyst_assets; $name, $format as $data);
256 };
257 ($name:literal, $format:ty as $data:ty) => {
258 $crate::register_format!(amethyst_assets; $name, $format as $data);
259 };
260 ($krate:ident; $name:literal, $format:ty as $data:ty) => {
261 $crate::inventory::submit!{
262 #![crate = $krate]
263 <dyn $crate::SerializableFormat<$data>>::format_register(
264 $name,
265 |deserializer| std::result::Result::Ok(
266 std::boxed::Box::new(
267 $crate::erased_serde::deserialize::<$format>(deserializer)?
268 ),
269 ),
270 )
271 }
272 impl $crate::SerializableFormat<$data> for $format {}
273 };
274}
275
276#[cfg(test)]
277mod tests {
278 use serde;
279 use serde_json;
280
281 use super::*;
282 use crate as amethyst_assets;
283 use crate::Format;
284 use amethyst_error::Error;
285
286 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
287 struct TestPrefab {
288 test: Box<dyn SerializableFormat<TestData>>,
289 }
290
291 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
292 struct TestData(String);
293 register_format_type!(TestData);
294
295 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
296 struct TestFormat(String);
297 register_format!("FOO", TestFormat as TestData);
298
299 impl Format<TestData> for TestFormat {
300 fn name(&self) -> &'static str {
301 "FOO"
302 }
303
304 fn import_simple(&self, _bytes: Vec<u8>) -> Result<TestData, Error> {
305 Ok(TestData(self.0.clone()))
307 }
308 }
309
310 #[test]
311 fn test_format_serialize() {
312 let prefab = TestPrefab {
313 test: Box::new(TestFormat("test string".to_owned())),
314 };
315
316 let serialized_prefab = serde_json::to_value(&prefab).unwrap();
318 let deserialized_prefab: TestPrefab = serde_json::from_value(serialized_prefab).unwrap();
319 assert_eq!(
320 prefab.test.import_simple(Vec::new()).unwrap(),
321 deserialized_prefab.test.import_simple(Vec::new()).unwrap()
322 );
323 }
324}