repr_c_impl/
visitor.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2use crate::layout::{
3    Annotation, Array, BuiltinType, Layout, Record, RecordField, Type, TypeVariant,
4};
5
6/// This trait represents a visitor that walks through a [`Type`].
7///
8/// Each method's default implementation is accessible through the function of the same name in the
9/// `visitor` module.
10///
11/// # Example
12///
13/// ```
14/// # use repr_c_impl::layout::{Layout, Type};
15/// # use repr_c_impl::visitor::{Visitor, visit_enum};
16/// struct Impl;
17///
18/// impl<I: Layout> Visitor<I> for Impl {
19///     fn visit_enum(&mut self, variants: &[i128], ty: &Type<I>) {
20///         println!("Variants: {:?}", variants);
21///         visit_enum(self, variants, ty)
22///     }
23/// }
24/// ```
25pub trait Visitor<I: Layout> {
26    /// Called for types.
27    fn visit_type(&mut self, ty: &Type<I>) {
28        visit_type(self, ty);
29    }
30
31    /// Called for the annotations on a type or field.
32    fn visit_annotations(&mut self, annotations: &[Annotation]) {
33        visit_annotations(self, annotations);
34    }
35
36    /// Called for builtin types.
37    fn visit_builtin_type(&mut self, builtin_type: BuiltinType, ty: &Type<I>) {
38        visit_builtin_type(self, builtin_type, ty);
39    }
40
41    /// Called for records.
42    fn visit_record(&mut self, record: &Record<I>, ty: &Type<I>) {
43        visit_record(self, record, ty);
44    }
45
46    /// Called for record fields.
47    fn visit_record_field(&mut self, field: &RecordField<I>, record: &Record<I>, ty: &Type<I>) {
48        visit_record_field(self, field, record, ty);
49    }
50
51    /// Called for typedefs.
52    fn visit_typedef(&mut self, dst: &Type<I>, ty: &Type<I>) {
53        visit_typedef(self, dst, ty);
54    }
55
56    /// Called for arrays.
57    fn visit_array(&mut self, array: &Array<I>, ty: &Type<I>) {
58        visit_array(self, array, ty);
59    }
60
61    /// Called for opaque types.
62    fn visit_opaque_type(&mut self, layout: I::OpaqueLayout, ty: &Type<I>) {
63        visit_opaque_type(self, layout, ty);
64    }
65
66    /// Called for enums.
67    fn visit_enum(&mut self, variants: &[i128], ty: &Type<I>) {
68        visit_enum(self, variants, ty);
69    }
70}
71
72/// The default implementation of `Visitor::visit_type`.
73pub fn visit_type<I: Layout>(visitor: &mut (impl Visitor<I> + ?Sized), ty: &Type<I>) {
74    visitor.visit_annotations(&ty.annotations);
75    match &ty.variant {
76        TypeVariant::Builtin(bi) => visitor.visit_builtin_type(*bi, ty),
77        TypeVariant::Record(rt) => visitor.visit_record(rt, ty),
78        TypeVariant::Typedef(td) => visitor.visit_typedef(td, ty),
79        TypeVariant::Array(at) => visitor.visit_array(at, ty),
80        TypeVariant::Opaque(l) => visitor.visit_opaque_type(*l, ty),
81        TypeVariant::Enum(l) => visitor.visit_enum(l, ty),
82    }
83}
84
85/// The default implementation of `Visitor::visit_record`.
86pub fn visit_record<I: Layout>(
87    visitor: &mut (impl Visitor<I> + ?Sized),
88    record: &Record<I>,
89    ty: &Type<I>,
90) {
91    for f in &record.fields {
92        visitor.visit_record_field(f, record, ty);
93    }
94}
95
96/// The default implementation of `Visitor::visit_annotations`.
97pub fn visit_annotations<I: Layout>(
98    visitor: &mut (impl Visitor<I> + ?Sized),
99    annotations: &[Annotation],
100) {
101    let _ = visitor;
102    let _ = annotations;
103    // nothing
104}
105
106/// The default implementation of `Visitor::visit_builtin_type`.
107pub fn visit_builtin_type<I: Layout>(
108    visitor: &mut (impl Visitor<I> + ?Sized),
109    builtin_type: BuiltinType,
110    ty: &Type<I>,
111) {
112    let _ = visitor;
113    let _ = builtin_type;
114    let _ = ty;
115    // nothing
116}
117
118/// The default implementation of `Visitor::visit_typedef`.
119pub fn visit_typedef<I: Layout>(
120    visitor: &mut (impl Visitor<I> + ?Sized),
121    dst: &Type<I>,
122    ty: &Type<I>,
123) {
124    let _ = visitor;
125    let _ = ty;
126    visitor.visit_type(dst);
127}
128
129/// The default implementation of `Visitor::visit_record`.
130pub fn visit_record_field<I: Layout>(
131    visitor: &mut (impl Visitor<I> + ?Sized),
132    field: &RecordField<I>,
133    record: &Record<I>,
134    ty: &Type<I>,
135) {
136    let _ = record;
137    let _ = ty;
138    visitor.visit_annotations(&field.annotations);
139    visitor.visit_type(&field.ty);
140}
141
142/// The default implementation of `Visitor::visit_array`.
143pub fn visit_array<I: Layout>(
144    visitor: &mut (impl Visitor<I> + ?Sized),
145    array: &Array<I>,
146    ty: &Type<I>,
147) {
148    let _ = ty;
149    visitor.visit_type(&array.element_type);
150}
151
152/// The default implementation of `Visitor::visit_opaque_type`.
153pub fn visit_opaque_type<I: Layout>(
154    visitor: &mut (impl Visitor<I> + ?Sized),
155    layout: I::OpaqueLayout,
156    ty: &Type<I>,
157) {
158    let _ = visitor;
159    let _ = layout;
160    let _ = ty;
161    // nothing
162}
163
164/// The default implementation of `Visitor::visit_enum`.
165pub fn visit_enum<I: Layout>(
166    visitor: &mut (impl Visitor<I> + ?Sized),
167    variants: &[i128],
168    ty: &Type<I>,
169) {
170    let _ = visitor;
171    let _ = variants;
172    let _ = ty;
173    // nothing
174}