gltf_v1_json/
common.rs

1use std::{fmt, marker};
2
3use crate::{
4    Path, Root,
5    gltf::Get,
6    validation::{self, Validate},
7};
8
9pub struct StringIndex<T>(String, marker::PhantomData<fn() -> T>);
10
11impl<T> StringIndex<T> {
12    /// Creates a new `Index` representing an offset into an array containing `T`.
13    pub fn new(value: String) -> Self {
14        StringIndex(value, std::marker::PhantomData)
15    }
16
17    /// Returns the internal offset value.
18    pub fn value(&self) -> &str {
19        &self.0
20    }
21}
22
23impl<T> serde::Serialize for StringIndex<T> {
24    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
25    where
26        S: ::serde::Serializer,
27    {
28        serializer.serialize_str(self.value())
29    }
30}
31
32impl<'de, T> serde::Deserialize<'de> for StringIndex<T> {
33    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
34    where
35        D: serde::Deserializer<'de>,
36    {
37        struct Visitor<T>(marker::PhantomData<T>);
38        impl<T> serde::de::Visitor<'_> for Visitor<T> {
39            type Value = StringIndex<T>;
40
41            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
42                formatter.write_str("index into child of root")
43            }
44
45            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
46            where
47                E: serde::de::Error,
48            {
49                Ok(StringIndex::new(v.to_string()))
50            }
51
52            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
53            where
54                E: serde::de::Error,
55            {
56                Ok(StringIndex::new(v))
57            }
58        }
59        deserializer.deserialize_str(Visitor::<T>(marker::PhantomData))
60    }
61}
62
63impl<T> Ord for StringIndex<T> {
64    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
65        self.0.cmp(&other.0)
66    }
67}
68impl<T> PartialOrd for StringIndex<T> {
69    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
70        Some(self.cmp(other))
71    }
72}
73
74impl<T> Eq for StringIndex<T> {}
75impl<T> PartialEq for StringIndex<T> {
76    fn eq(&self, other: &Self) -> bool {
77        self.0 == other.0
78    }
79}
80
81impl<T> std::hash::Hash for StringIndex<T> {
82    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
83        self.0.hash(state);
84    }
85}
86
87impl<T> fmt::Debug for StringIndex<T> {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        write!(f, "{}", self.0)
90    }
91}
92
93impl<T> fmt::Display for StringIndex<T> {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        write!(f, "{}", self.0)
96    }
97}
98
99impl<T> Clone for StringIndex<T> {
100    fn clone(&self) -> Self {
101        Self::new(self.0.clone())
102    }
103}
104
105impl<T> Validate for StringIndex<T>
106where
107    Root: Get<T>,
108{
109    fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
110    where
111        P: Fn() -> Path,
112        R: FnMut(&dyn Fn() -> Path, validation::Error),
113    {
114        if root.get(self.clone()).is_none() {
115            report(&path, validation::Error::IndexNotFound);
116        }
117    }
118}