assimp/
internal_macros.rs

1// TODO: Quite messy macro stuff, needs documenting/tidying up
2
3// Define the iterator struct and constructor from raw data.
4// Same for all data types.
5macro_rules! define_iter {
6    ($(#[$iter_attr:meta])* struct $name:ident -> $raw:ty) => (
7        $(#[$iter_attr])*
8        pub struct $name<'a> {
9            ptr: $raw,
10            idx: isize,
11            len: usize,
12            _mk: ::std::marker::PhantomData<&'a ()>
13        }
14
15        #[doc(hidden)]
16        impl<'a> $name<'a> {
17            pub fn new(ptr: $raw, len: usize) -> $name<'a> {
18                $name { ptr: ptr, idx: 0, len: len, _mk: ::std::marker::PhantomData }
19            }
20        }
21    )
22}
23
24macro_rules! impl_iterator {
25    ($name:ident, $item:ident) => (
26        impl<'a> Iterator for $name<'a> {
27            type Item = $item<'a>;
28            fn next(&mut self) -> Option<$item<'a>> {
29                if self.idx < self.len as isize {
30                    let item = $item::from_raw(unsafe { self.ptr.offset(self.idx) });
31                    self.idx = self.idx + 1;
32                    Some(item)
33                } else {
34                    None
35                }
36            }
37        }
38
39        impl<'a> ExactSizeIterator for $name<'a> {
40            fn len(&self) -> usize { self.len }
41        }
42    )
43}
44
45macro_rules! impl_iterator_indirect {
46    ($name:ident, $item:ident) => (
47        impl<'a> Iterator for $name<'a> {
48            type Item = $item<'a>;
49            fn next(&mut self) -> Option<$item<'a>> {
50                if self.idx < self.len as isize {
51                    let item = $item::from_raw(unsafe { *self.ptr.offset(self.idx) });
52                    self.idx = self.idx + 1;
53                    Some(item)
54                } else {
55                    None
56                }
57            }
58        }
59
60        impl<'a> ExactSizeIterator for $name<'a> {
61            fn len(&self) -> usize { self.len }
62        }
63    )
64}
65
66macro_rules! impl_iterator_pod {
67    ($name:ident, $item:ident) => (
68        impl<'a> Iterator for $name<'a> {
69            type Item = $item;
70            fn next(&mut self) -> Option<$item> {
71                if self.idx < self.len as isize {
72                    let item = $item::from_raw(unsafe { self.ptr.offset(self.idx) });
73                    self.idx = self.idx + 1;
74                    Some(item)
75                } else {
76                    None
77                }
78            }
79        }
80    )
81}
82
83macro_rules! define_type {
84    // Reference type
85    ($(#[$type_attr:meta])* struct $name:ident(&$raw:ty)) => (
86        $(#[$type_attr])*
87        pub struct $name<'a>(&'a $raw);
88
89        #[doc(hidden)]
90        impl<'a> $name<'a> {
91            pub fn from_raw(raw: *const $raw) -> $name<'a> {
92                unsafe { $name(&*raw) }
93            }
94            pub fn to_raw(&self) -> *const $raw {
95                self.0
96            }
97        }
98
99        impl<'a> ::std::ops::Deref for $name<'a> {
100            type Target = $raw;
101            fn deref<'b>(&'b self) -> &'b $raw { &self.0 }
102        }
103    );
104    // Non-reference type = POD
105    ($(#[$type_attr:meta])* struct $name:ident($raw:ty)) => (
106        $(#[$type_attr])*
107        pub struct $name($raw);
108
109        #[doc(hidden)]
110        impl $name {
111            pub fn from_raw(raw: *const $raw) -> $name {
112                unsafe { $name(*raw) }
113            }
114        }
115
116        impl ::std::ops::Deref for $name {
117            type Target = $raw;
118            fn deref<'a>(&'a self) -> &'a $raw { &self.0 }
119        }
120    );
121}
122
123macro_rules! define_type_and_iterator {
124    (
125        $(#[$type_attr:meta])* struct $type_name:ident(&$raw:ty)
126        $(#[$iter_attr:meta])* struct $iter_name:ident
127    ) => (
128        define_type!($(#[$type_attr])* struct $type_name(&$raw));
129        define_iter!($(#[$iter_attr])* struct $iter_name -> *const $raw);
130        impl_iterator!($iter_name, $type_name);
131    );
132    (
133        $(#[$type_attr:meta])* struct $type_name:ident($raw:ty)
134        $(#[$iter_attr:meta])* struct $iter_name:ident
135    ) => (
136        define_type!($(#[$type_attr])* struct $type_name($raw));
137        define_iter!($(#[$iter_attr])* struct $iter_name -> *const $raw);
138        impl_iterator_pod!($iter_name, $type_name);
139    );
140}
141
142macro_rules! define_type_and_iterator_indirect {
143    (
144        $(#[$type_attr:meta])* struct $type_name:ident(&$raw:ty)
145        $(#[$iter_attr:meta])* struct $iter_name:ident
146    ) => (
147        define_type!($(#[$type_attr])* struct $type_name(&$raw));
148        define_iter!($(#[$iter_attr])* struct $iter_name -> *const *const $raw);
149        impl_iterator_indirect!($iter_name, $type_name);
150    );
151}