]> git.proxmox.com Git - rustc.git/blob - vendor/windows-bindgen/src/rust/iterators.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / windows-bindgen / src / rust / iterators.rs
1 use super::*;
2
3 pub fn writer(writer: &Writer, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, cfg: &Cfg) -> TokenStream {
4 match writer.reader.type_def_type_name(def) {
5 // If the type is IIterator<T> then simply implement the Iterator trait over top.
6 TypeName::IIterator => {
7 return quote! {
8 impl<T: ::windows_core::RuntimeType> ::core::iter::Iterator for IIterator<T> {
9 type Item = T;
10
11 fn next(&mut self) -> ::core::option::Option<Self::Item> {
12 let result = self.Current().ok();
13
14 if result.is_some() {
15 self.MoveNext().ok()?;
16 }
17
18 result
19 }
20 }
21 };
22 }
23 // If the type is IIterable<T> then implement the IntoIterator trait and rely on the resulting
24 // IIterator<T> returned by first() to implement the Iterator trait.
25 TypeName::IIterable => {
26 return quote! {
27 impl<T: ::windows_core::RuntimeType> ::core::iter::IntoIterator for IIterable<T> {
28 type Item = T;
29 type IntoIter = IIterator<Self::Item>;
30
31 fn into_iter(self) -> Self::IntoIter {
32 ::core::iter::IntoIterator::into_iter(&self)
33 }
34 }
35 impl<T: ::windows_core::RuntimeType> ::core::iter::IntoIterator for &IIterable<T> {
36 type Item = T;
37 type IntoIter = IIterator<Self::Item>;
38
39 fn into_iter(self) -> Self::IntoIter {
40 // TODO: not sure how to avoid this unwrap, although it should always succeed in practice.
41 self.First().unwrap()
42 }
43 }
44 };
45 }
46 // If the type is IVectorView<T> then provide the VectorViewIterator fast iterator.
47 TypeName::IVectorView => {
48 return quote! {
49 pub struct VectorViewIterator<T: ::windows_core::RuntimeType + 'static> {
50 vector: ::core::option::Option<IVectorView<T>>,
51 current: u32,
52 }
53
54 impl<T: ::windows_core::RuntimeType> VectorViewIterator<T> {
55 pub fn new(vector: ::core::option::Option<IVectorView<T>>) -> Self {
56 Self { vector, current: 0 }
57 }
58 }
59
60 impl<T: ::windows_core::RuntimeType> ::core::iter::Iterator for VectorViewIterator<T> {
61 type Item = T;
62
63 fn next(&mut self) -> ::core::option::Option<Self::Item> {
64 self.vector.as_ref()
65 .and_then(|vector| {
66 vector.GetAt(self.current).ok()
67 })
68 .and_then(|result| {
69 self.current += 1;
70 Some(result)
71 })
72 }
73 }
74
75 impl<T: ::windows_core::RuntimeType> ::core::iter::IntoIterator for IVectorView<T> {
76 type Item = T;
77 type IntoIter = VectorViewIterator<Self::Item>;
78
79 fn into_iter(self) -> Self::IntoIter {
80 ::core::iter::IntoIterator::into_iter(&self)
81 }
82 }
83 impl<T: ::windows_core::RuntimeType> ::core::iter::IntoIterator for &IVectorView<T> {
84 type Item = T;
85 type IntoIter = VectorViewIterator<Self::Item>;
86
87 fn into_iter(self) -> Self::IntoIter {
88 // TODO: shouldn't need to clone - VectorViewIterator should hold a reference
89 VectorViewIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self)))
90 }
91 }
92 };
93 }
94 TypeName::IVector => {
95 return quote! {
96 pub struct VectorIterator<T: ::windows_core::RuntimeType + 'static> {
97 vector: ::core::option::Option<IVector<T>>,
98 current: u32,
99 }
100
101 impl<T: ::windows_core::RuntimeType> VectorIterator<T> {
102 pub fn new(vector: ::core::option::Option<IVector<T>>) -> Self {
103 Self { vector, current: 0 }
104 }
105 }
106
107 impl<T: ::windows_core::RuntimeType> ::core::iter::Iterator for VectorIterator<T> {
108 type Item = T;
109
110 fn next(&mut self) -> ::core::option::Option<Self::Item> {
111 self.vector.as_ref()
112 .and_then(|vector| {
113 vector.GetAt(self.current).ok()
114 })
115 .and_then(|result| {
116 self.current += 1;
117 Some(result)
118 })
119 }
120 }
121
122 impl<T: ::windows_core::RuntimeType> ::core::iter::IntoIterator for IVector<T> {
123 type Item = T;
124 type IntoIter = VectorIterator<Self::Item>;
125
126 fn into_iter(self) -> Self::IntoIter {
127 ::core::iter::IntoIterator::into_iter(&self)
128 }
129 }
130 impl<T: ::windows_core::RuntimeType> ::core::iter::IntoIterator for &IVector<T> {
131 type Item = T;
132 type IntoIter = VectorIterator<Self::Item>;
133
134 fn into_iter(self) -> Self::IntoIter {
135 // TODO: shouldn't need to clone - VectorIterator should hold a reference
136 VectorIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self)))
137 }
138 }
139 };
140 }
141 _ => {}
142 }
143
144 let wfc = writer.namespace("Windows.Foundation.Collections");
145 let mut iterable = None;
146 let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec()));
147
148 // If the class or interface is not one of the well-known collection interfaces, we then see whether it
149 // implements any one of them. Here is where we favor IVectorView/IVector over IIterable.
150 for interface in interfaces {
151 if let Type::TypeDef(interface, interface_generics) = &interface.ty {
152 match writer.reader.type_def_type_name(*interface) {
153 TypeName::IVectorView => {
154 let item = writer.type_name(&interface_generics[0]);
155 let mut cfg = cfg.clone();
156 type_def_cfg_combine(writer.reader, *interface, interface_generics, &mut cfg);
157 let features = writer.cfg_features(&cfg);
158
159 return quote! {
160 #features
161 impl<#constraints> ::core::iter::IntoIterator for #ident {
162 type Item = #item;
163 type IntoIter = #wfc VectorViewIterator<Self::Item>;
164
165 fn into_iter(self) -> Self::IntoIter {
166 ::core::iter::IntoIterator::into_iter(&self)
167 }
168 }
169 #features
170 impl<#constraints> ::core::iter::IntoIterator for &#ident {
171 type Item = #item;
172 type IntoIter = #wfc VectorViewIterator<Self::Item>;
173
174 fn into_iter(self) -> Self::IntoIter {
175 #wfc VectorViewIterator::new(::windows_core::ComInterface::cast(self).ok())
176 }
177 }
178 };
179 }
180 TypeName::IVector => {
181 let item = writer.type_name(&interface_generics[0]);
182 let mut cfg = cfg.clone();
183 type_def_cfg_combine(writer.reader, *interface, interface_generics, &mut cfg);
184 let features = writer.cfg_features(&cfg);
185
186 return quote! {
187 #features
188 impl<#constraints> ::core::iter::IntoIterator for #ident {
189 type Item = #item;
190 type IntoIter = #wfc VectorIterator<Self::Item>;
191
192 fn into_iter(self) -> Self::IntoIter {
193 ::core::iter::IntoIterator::into_iter(&self)
194 }
195 }
196 #features
197 impl<#constraints> ::core::iter::IntoIterator for &#ident {
198 type Item = #item;
199 type IntoIter = #wfc VectorIterator<Self::Item>;
200
201 fn into_iter(self) -> Self::IntoIter {
202 #wfc VectorIterator::new(::windows_core::ComInterface::cast(self).ok())
203 }
204 }
205 };
206 }
207 TypeName::IIterable => {
208 iterable = Some((*interface, interface_generics.to_vec()));
209 }
210 _ => {}
211 }
212 }
213 }
214
215 match iterable {
216 None => TokenStream::new(),
217 Some((interface, interface_generics)) => {
218 let item = writer.type_name(&interface_generics[0]);
219 let mut cfg = cfg.clone();
220 type_def_cfg_combine(writer.reader, interface, &interface_generics, &mut cfg);
221 let features = writer.cfg_features(&cfg);
222
223 quote! {
224 #features
225 impl<#constraints> ::core::iter::IntoIterator for #ident {
226 type Item = #item;
227 type IntoIter = #wfc IIterator<Self::Item>;
228
229 fn into_iter(self) -> Self::IntoIter {
230 ::core::iter::IntoIterator::into_iter(&self)
231 }
232 }
233 #features
234 impl<#constraints> ::core::iter::IntoIterator for &#ident {
235 type Item = #item;
236 type IntoIter = #wfc IIterator<Self::Item>;
237
238 fn into_iter(self) -> Self::IntoIter {
239 // TODO: not sure how to avoid this unwrap, although it should always succeed in practice.
240 self.First().unwrap()
241 }
242 }
243 }
244 }
245 }
246 }