dae_parser/api/
mod.rs

1pub mod geom;
2pub mod local_map;
3pub mod source;
4
5use ref_cast::RefCast;
6use std::{collections::HashMap, marker::PhantomData, ops::Index};
7
8use super::*;
9pub(crate) use local_map::{CollectLocalMaps, HasId, Traversable};
10pub use local_map::{LocalMap, LocalMaps};
11
12/// A wrapper around a base type `A` to indicate that the value is pointing to
13/// a value of type `T`.
14///
15/// This is not a strict type safety barrier; it is possible to convert a `Ref`
16/// to and from its raw version. However this can help in API documentation,
17/// as well as to assist type inference in functions like [`LocalMap::get`].
18#[derive(Copy, Clone, RefCast)]
19#[repr(transparent)]
20pub struct Ref<A, T: ?Sized> {
21    /// The underlying storage or "raw" value.
22    pub val: A,
23    _marker: PhantomData<T>,
24}
25
26impl<A: Display, T: ?Sized> Display for Ref<A, T> {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        self.val.fmt(f)
29    }
30}
31
32impl<A: Debug, T: ?Sized> Debug for Ref<A, T> {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        self.val.fmt(f)
35    }
36}
37
38/// A strongly typed URL referencing a `T`.
39pub type UrlRef<T> = Ref<Url, T>;
40
41/// A strongly typed string referencing a `T`.
42pub type NameRef<T> = Ref<String, T>;
43
44impl<A, T: ?Sized> Deref for Ref<A, T> {
45    type Target = A;
46
47    fn deref(&self) -> &Self::Target {
48        &self.val
49    }
50}
51
52impl<A, T: ?Sized> Ref<A, T> {
53    /// Construct a new `Ref` by wrapping a raw value.
54    pub fn new(val: A) -> Self {
55        Self {
56            val,
57            _marker: PhantomData,
58        }
59    }
60}
61
62impl<A: FromStr, T: ?Sized> FromStr for Ref<A, T> {
63    type Err = A::Err;
64
65    fn from_str(s: &str) -> Result<Self, Self::Err> {
66        A::from_str(s).map(Ref::new)
67    }
68}
69
70impl Document {
71    /// Returns an iterator over `Library<T>` elements.
72    pub fn library_iter<T>(&self) -> LibraryIter<'_, T> {
73        LibraryIter {
74            iter: self.library.iter(),
75            _marker: PhantomData,
76        }
77    }
78    /// Returns an iterator over all elements of type `T`.
79    pub fn iter<T>(&self) -> ItemIter<'_, T> {
80        ItemIter {
81            iter: self.library_iter(),
82            item: [].iter(),
83        }
84    }
85}
86
87/// An iterator over all `Library<T>` elements for a particular `T`,
88/// returned by [`Document::library_iter`].
89#[derive(Debug)]
90pub struct LibraryIter<'a, T> {
91    iter: std::slice::Iter<'a, LibraryElement>,
92    _marker: PhantomData<T>,
93}
94
95impl<'a, T: ParseLibrary + 'a> Iterator for LibraryIter<'a, T> {
96    type Item = &'a Library<T>;
97
98    fn next(&mut self) -> Option<Self::Item> {
99        for lib in &mut self.iter {
100            if let Some(lib) = T::extract_element(lib) {
101                return Some(lib);
102            }
103        }
104        None
105    }
106}
107
108/// An iterator over all `T` elements for a `ParseLibrary` type `T`,
109/// returned by [`Document::iter`].
110#[derive(Debug)]
111pub struct ItemIter<'a, T> {
112    iter: LibraryIter<'a, T>,
113    item: std::slice::Iter<'a, T>,
114}
115
116impl<'a, T: ParseLibrary + 'a> Iterator for ItemIter<'a, T> {
117    type Item = &'a T;
118    fn next(&mut self) -> Option<Self::Item> {
119        loop {
120            if let Some(e) = self.item.next() {
121                return Some(e);
122            }
123            if let Some(lib) = self.iter.next() {
124                self.item = lib.items.iter();
125            } else {
126                return None;
127            }
128        }
129    }
130}