]> git.lizzy.rs Git - rust.git/blob - src/libstd/reflect.rs
Convert most code to new inner attribute syntax.
[rust.git] / src / libstd / reflect.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12
13 Runtime type reflection
14
15 */
16
17 #![allow(missing_doc)]
18
19 use intrinsics::{Disr, Opaque, TyDesc, TyVisitor};
20 use mem;
21 use raw;
22
23 /**
24  * Trait for visitor that wishes to reflect on data. To use this, create a
25  * struct that encapsulates the set of pointers you wish to walk through a
26  * data structure, and implement both `MovePtr` for it as well as `TyVisitor`;
27  * then build a MovePtrAdaptor wrapped around your struct.
28  */
29 pub trait MovePtr {
30     fn move_ptr(&mut self, adjustment: |*u8| -> *u8);
31     fn push_ptr(&mut self);
32     fn pop_ptr(&mut self);
33 }
34
35 /// Helper function for alignment calculation.
36 #[inline]
37 pub fn align(size: uint, align: uint) -> uint {
38     ((size + align) - 1u) & !(align - 1u)
39 }
40
41 /// Adaptor to wrap around visitors implementing MovePtr.
42 pub struct MovePtrAdaptor<V> {
43     priv inner: V
44 }
45 pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> {
46     MovePtrAdaptor { inner: v }
47 }
48
49 impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> {
50     #[inline]
51     pub fn bump(&mut self, sz: uint) {
52         self.inner.move_ptr(|p| ((p as uint) + sz) as *u8)
53     }
54
55     #[inline]
56     pub fn align(&mut self, a: uint) {
57         self.inner.move_ptr(|p| align(p as uint, a) as *u8)
58     }
59
60     #[inline]
61     pub fn align_to<T>(&mut self) {
62         self.align(mem::min_align_of::<T>());
63     }
64
65     #[inline]
66     pub fn bump_past<T>(&mut self) {
67         self.bump(mem::size_of::<T>());
68     }
69
70     pub fn unwrap(self) -> V { self.inner }
71 }
72
73 /// Abstract type-directed pointer-movement using the MovePtr trait
74 impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
75     fn visit_bot(&mut self) -> bool {
76         self.align_to::<()>();
77         if ! self.inner.visit_bot() { return false; }
78         self.bump_past::<()>();
79         true
80     }
81
82     fn visit_nil(&mut self) -> bool {
83         self.align_to::<()>();
84         if ! self.inner.visit_nil() { return false; }
85         self.bump_past::<()>();
86         true
87     }
88
89     fn visit_bool(&mut self) -> bool {
90         self.align_to::<bool>();
91         if ! self.inner.visit_bool() { return false; }
92         self.bump_past::<bool>();
93         true
94     }
95
96     fn visit_int(&mut self) -> bool {
97         self.align_to::<int>();
98         if ! self.inner.visit_int() { return false; }
99         self.bump_past::<int>();
100         true
101     }
102
103     fn visit_i8(&mut self) -> bool {
104         self.align_to::<i8>();
105         if ! self.inner.visit_i8() { return false; }
106         self.bump_past::<i8>();
107         true
108     }
109
110     fn visit_i16(&mut self) -> bool {
111         self.align_to::<i16>();
112         if ! self.inner.visit_i16() { return false; }
113         self.bump_past::<i16>();
114         true
115     }
116
117     fn visit_i32(&mut self) -> bool {
118         self.align_to::<i32>();
119         if ! self.inner.visit_i32() { return false; }
120         self.bump_past::<i32>();
121         true
122     }
123
124     fn visit_i64(&mut self) -> bool {
125         self.align_to::<i64>();
126         if ! self.inner.visit_i64() { return false; }
127         self.bump_past::<i64>();
128         true
129     }
130
131     fn visit_uint(&mut self) -> bool {
132         self.align_to::<uint>();
133         if ! self.inner.visit_uint() { return false; }
134         self.bump_past::<uint>();
135         true
136     }
137
138     fn visit_u8(&mut self) -> bool {
139         self.align_to::<u8>();
140         if ! self.inner.visit_u8() { return false; }
141         self.bump_past::<u8>();
142         true
143     }
144
145     fn visit_u16(&mut self) -> bool {
146         self.align_to::<u16>();
147         if ! self.inner.visit_u16() { return false; }
148         self.bump_past::<u16>();
149         true
150     }
151
152     fn visit_u32(&mut self) -> bool {
153         self.align_to::<u32>();
154         if ! self.inner.visit_u32() { return false; }
155         self.bump_past::<u32>();
156         true
157     }
158
159     fn visit_u64(&mut self) -> bool {
160         self.align_to::<u64>();
161         if ! self.inner.visit_u64() { return false; }
162         self.bump_past::<u64>();
163         true
164     }
165
166     fn visit_f32(&mut self) -> bool {
167         self.align_to::<f32>();
168         if ! self.inner.visit_f32() { return false; }
169         self.bump_past::<f32>();
170         true
171     }
172
173     fn visit_f64(&mut self) -> bool {
174         self.align_to::<f64>();
175         if ! self.inner.visit_f64() { return false; }
176         self.bump_past::<f64>();
177         true
178     }
179
180     fn visit_char(&mut self) -> bool {
181         self.align_to::<char>();
182         if ! self.inner.visit_char() { return false; }
183         self.bump_past::<char>();
184         true
185     }
186
187     fn visit_estr_box(&mut self) -> bool {
188         true
189     }
190
191     fn visit_estr_uniq(&mut self) -> bool {
192         self.align_to::<~str>();
193         if ! self.inner.visit_estr_uniq() { return false; }
194         self.bump_past::<~str>();
195         true
196     }
197
198     fn visit_estr_slice(&mut self) -> bool {
199         self.align_to::<&'static str>();
200         if ! self.inner.visit_estr_slice() { return false; }
201         self.bump_past::<&'static str>();
202         true
203     }
204
205     fn visit_estr_fixed(&mut self, n: uint,
206                         sz: uint,
207                         align: uint) -> bool {
208         self.align(align);
209         if ! self.inner.visit_estr_fixed(n, sz, align) { return false; }
210         self.bump(sz);
211         true
212     }
213
214     fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
215         self.align_to::<@u8>();
216         if ! self.inner.visit_box(mtbl, inner) { return false; }
217         self.bump_past::<@u8>();
218         true
219     }
220
221     fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
222         self.align_to::<~u8>();
223         if ! self.inner.visit_uniq(mtbl, inner) { return false; }
224         self.bump_past::<~u8>();
225         true
226     }
227
228     fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
229         self.align_to::<*u8>();
230         if ! self.inner.visit_ptr(mtbl, inner) { return false; }
231         self.bump_past::<*u8>();
232         true
233     }
234
235     fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
236         self.align_to::<&'static u8>();
237         if ! self.inner.visit_rptr(mtbl, inner) { return false; }
238         self.bump_past::<&'static u8>();
239         true
240     }
241
242     fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
243         self.align_to::<raw::Vec<()>>();
244         if ! self.inner.visit_vec(mtbl, inner) { return false; }
245         true
246     }
247
248     fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
249         self.align_to::<~[u8]>();
250         if ! self.inner.visit_vec(mtbl, inner) { return false; }
251         self.bump_past::<~[u8]>();
252         true
253     }
254
255     fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool {
256         true
257     }
258
259     fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
260         self.align_to::<~[u8]>();
261         if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
262         self.bump_past::<~[u8]>();
263         true
264     }
265
266     fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
267         self.align_to::<&'static [u8]>();
268         if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
269         self.bump_past::<&'static [u8]>();
270         true
271     }
272
273     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
274                         mtbl: uint, inner: *TyDesc) -> bool {
275         self.align(align);
276         if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
277             return false;
278         }
279         self.bump(sz);
280         true
281     }
282
283     fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
284         self.align(align);
285         if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; }
286         true
287     }
288
289     fn visit_rec_field(&mut self, i: uint, name: &str,
290                        mtbl: uint, inner: *TyDesc) -> bool {
291         unsafe { self.align((*inner).align); }
292         if ! self.inner.visit_rec_field(i, name, mtbl, inner) {
293             return false;
294         }
295         unsafe { self.bump((*inner).size); }
296         true
297     }
298
299     fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
300         if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; }
301         true
302     }
303
304     fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, sz: uint,
305                          align: uint) -> bool {
306         self.align(align);
307         if ! self.inner.visit_enter_class(name, named_fields, n_fields, sz, align) {
308             return false;
309         }
310         true
311     }
312
313     fn visit_class_field(&mut self, i: uint, name: &str, named: bool, mtbl: uint,
314                          inner: *TyDesc) -> bool {
315         unsafe { self.align((*inner).align); }
316         if ! self.inner.visit_class_field(i, name, named, mtbl, inner) {
317             return false;
318         }
319         unsafe { self.bump((*inner).size); }
320         true
321     }
322
323     fn visit_leave_class(&mut self, name: &str, named_fields: bool, n_fields: uint, sz: uint,
324                          align: uint) -> bool {
325         if ! self.inner.visit_leave_class(name, named_fields, n_fields, sz, align) {
326             return false;
327         }
328         true
329     }
330
331     fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
332         self.align(align);
333         if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; }
334         true
335     }
336
337     fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool {
338         unsafe { self.align((*inner).align); }
339         if ! self.inner.visit_tup_field(i, inner) { return false; }
340         unsafe { self.bump((*inner).size); }
341         true
342     }
343
344     fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
345         if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; }
346         true
347     }
348
349     fn visit_enter_fn(&mut self, purity: uint, proto: uint,
350                       n_inputs: uint, retstyle: uint) -> bool {
351         if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
352             return false
353         }
354         true
355     }
356
357     fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool {
358         if ! self.inner.visit_fn_input(i, mode, inner) { return false; }
359         true
360     }
361
362     fn visit_fn_output(&mut self, retstyle: uint, variadic: bool, inner: *TyDesc) -> bool {
363         if ! self.inner.visit_fn_output(retstyle, variadic, inner) { return false; }
364         true
365     }
366
367     fn visit_leave_fn(&mut self, purity: uint, proto: uint,
368                       n_inputs: uint, retstyle: uint) -> bool {
369         if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) {
370             return false;
371         }
372         true
373     }
374
375     fn visit_enter_enum(&mut self, n_variants: uint,
376                         get_disr: extern unsafe fn(ptr: *Opaque) -> Disr,
377                         sz: uint, align: uint)
378                      -> bool {
379         self.align(align);
380         if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) {
381             return false;
382         }
383         true
384     }
385
386     fn visit_enter_enum_variant(&mut self, variant: uint,
387                                 disr_val: Disr,
388                                 n_fields: uint,
389                                 name: &str) -> bool {
390         if ! self.inner.visit_enter_enum_variant(variant, disr_val,
391                                                  n_fields, name) {
392             return false;
393         }
394         true
395     }
396
397     fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool {
398         self.inner.push_ptr();
399         self.bump(offset);
400         if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; }
401         self.inner.pop_ptr();
402         true
403     }
404
405     fn visit_leave_enum_variant(&mut self, variant: uint,
406                                 disr_val: Disr,
407                                 n_fields: uint,
408                                 name: &str) -> bool {
409         if ! self.inner.visit_leave_enum_variant(variant, disr_val,
410                                                  n_fields, name) {
411             return false;
412         }
413         true
414     }
415
416     fn visit_leave_enum(&mut self, n_variants: uint,
417                         get_disr: extern unsafe fn(ptr: *Opaque) -> Disr,
418                         sz: uint, align: uint) -> bool {
419         if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
420             return false;
421         }
422         self.bump(sz);
423         true
424     }
425
426     fn visit_trait(&mut self, name: &str) -> bool {
427         self.align_to::<~TyVisitor>();
428         if ! self.inner.visit_trait(name) { return false; }
429         self.bump_past::<~TyVisitor>();
430         true
431     }
432
433     fn visit_param(&mut self, i: uint) -> bool {
434         if ! self.inner.visit_param(i) { return false; }
435         true
436     }
437
438     fn visit_self(&mut self) -> bool {
439         self.align_to::<&'static u8>();
440         if ! self.inner.visit_self() { return false; }
441         self.align_to::<&'static u8>();
442         true
443     }
444 }