iceberg/spec/schema/
visitor.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use super::*;
19
20/// A post order schema visitor.
21///
22/// For order of methods called, please refer to [`visit_schema`].
23pub trait SchemaVisitor {
24    /// Return type of this visitor.
25    type T;
26
27    /// Called before struct field.
28    fn before_struct_field(&mut self, _field: &NestedFieldRef) -> Result<()> {
29        Ok(())
30    }
31    /// Called after struct field.
32    fn after_struct_field(&mut self, _field: &NestedFieldRef) -> Result<()> {
33        Ok(())
34    }
35    /// Called before list field.
36    fn before_list_element(&mut self, _field: &NestedFieldRef) -> Result<()> {
37        Ok(())
38    }
39    /// Called after list field.
40    fn after_list_element(&mut self, _field: &NestedFieldRef) -> Result<()> {
41        Ok(())
42    }
43    /// Called before map key field.
44    fn before_map_key(&mut self, _field: &NestedFieldRef) -> Result<()> {
45        Ok(())
46    }
47    /// Called after map key field.
48    fn after_map_key(&mut self, _field: &NestedFieldRef) -> Result<()> {
49        Ok(())
50    }
51    /// Called before map value field.
52    fn before_map_value(&mut self, _field: &NestedFieldRef) -> Result<()> {
53        Ok(())
54    }
55    /// Called after map value field.
56    fn after_map_value(&mut self, _field: &NestedFieldRef) -> Result<()> {
57        Ok(())
58    }
59
60    /// Called after schema's type visited.
61    fn schema(&mut self, schema: &Schema, value: Self::T) -> Result<Self::T>;
62    /// Called after struct's field type visited.
63    fn field(&mut self, field: &NestedFieldRef, value: Self::T) -> Result<Self::T>;
64    /// Called after struct's fields visited.
65    fn r#struct(&mut self, r#struct: &StructType, results: Vec<Self::T>) -> Result<Self::T>;
66    /// Called after list fields visited.
67    fn list(&mut self, list: &ListType, value: Self::T) -> Result<Self::T>;
68    /// Called after map's key and value fields visited.
69    fn map(&mut self, map: &MapType, key_value: Self::T, value: Self::T) -> Result<Self::T>;
70    /// Called when see a primitive type.
71    fn primitive(&mut self, p: &PrimitiveType) -> Result<Self::T>;
72}
73
74/// Visiting a type in post order.
75pub(crate) fn visit_type<V: SchemaVisitor>(r#type: &Type, visitor: &mut V) -> Result<V::T> {
76    match r#type {
77        Type::Primitive(p) => visitor.primitive(p),
78        Type::List(list) => {
79            visitor.before_list_element(&list.element_field)?;
80            let value = visit_type(&list.element_field.field_type, visitor)?;
81            visitor.after_list_element(&list.element_field)?;
82            visitor.list(list, value)
83        }
84        Type::Map(map) => {
85            let key_result = {
86                visitor.before_map_key(&map.key_field)?;
87                let ret = visit_type(&map.key_field.field_type, visitor)?;
88                visitor.after_map_key(&map.key_field)?;
89                ret
90            };
91
92            let value_result = {
93                visitor.before_map_value(&map.value_field)?;
94                let ret = visit_type(&map.value_field.field_type, visitor)?;
95                visitor.after_map_value(&map.value_field)?;
96                ret
97            };
98
99            visitor.map(map, key_result, value_result)
100        }
101        Type::Struct(s) => visit_struct(s, visitor),
102    }
103}
104
105/// Visit struct type in post order.
106pub fn visit_struct<V: SchemaVisitor>(s: &StructType, visitor: &mut V) -> Result<V::T> {
107    let mut results = Vec::with_capacity(s.fields().len());
108    for field in s.fields() {
109        visitor.before_struct_field(field)?;
110        let result = visit_type(&field.field_type, visitor)?;
111        visitor.after_struct_field(field)?;
112        let result = visitor.field(field, result)?;
113        results.push(result);
114    }
115
116    visitor.r#struct(s, results)
117}
118
119/// Visit schema in post order.
120pub fn visit_schema<V: SchemaVisitor>(schema: &Schema, visitor: &mut V) -> Result<V::T> {
121    let result = visit_struct(&schema.r#struct, visitor)?;
122    visitor.schema(schema, result)
123}
124
125/// A post order schema visitor with partner.
126///
127/// For order of methods called, please refer to [`visit_schema_with_partner`].
128pub trait SchemaWithPartnerVisitor<P> {
129    /// Return type of this visitor.
130    type T;
131
132    /// Called before struct field.
133    fn before_struct_field(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
134        Ok(())
135    }
136    /// Called after struct field.
137    fn after_struct_field(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
138        Ok(())
139    }
140    /// Called before list field.
141    fn before_list_element(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
142        Ok(())
143    }
144    /// Called after list field.
145    fn after_list_element(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
146        Ok(())
147    }
148    /// Called before map key field.
149    fn before_map_key(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
150        Ok(())
151    }
152    /// Called after map key field.
153    fn after_map_key(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
154        Ok(())
155    }
156    /// Called before map value field.
157    fn before_map_value(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
158        Ok(())
159    }
160    /// Called after map value field.
161    fn after_map_value(&mut self, _field: &NestedFieldRef, _partner: &P) -> Result<()> {
162        Ok(())
163    }
164
165    /// Called after schema's type visited.
166    fn schema(&mut self, schema: &Schema, partner: &P, value: Self::T) -> Result<Self::T>;
167    /// Called after struct's field type visited.
168    fn field(&mut self, field: &NestedFieldRef, partner: &P, value: Self::T) -> Result<Self::T>;
169    /// Called after struct's fields visited.
170    fn r#struct(
171        &mut self,
172        r#struct: &StructType,
173        partner: &P,
174        results: Vec<Self::T>,
175    ) -> Result<Self::T>;
176    /// Called after list fields visited.
177    fn list(&mut self, list: &ListType, partner: &P, value: Self::T) -> Result<Self::T>;
178    /// Called after map's key and value fields visited.
179    fn map(
180        &mut self,
181        map: &MapType,
182        partner: &P,
183        key_value: Self::T,
184        value: Self::T,
185    ) -> Result<Self::T>;
186    /// Called when see a primitive type.
187    fn primitive(&mut self, p: &PrimitiveType, partner: &P) -> Result<Self::T>;
188}
189
190/// Accessor used to get child partner from parent partner.
191pub trait PartnerAccessor<P> {
192    /// Get the struct partner from schema partner.
193    fn struct_partner<'a>(&self, schema_partner: &'a P) -> Result<&'a P>;
194    /// Get the field partner from struct partner.
195    fn field_partner<'a>(&self, struct_partner: &'a P, field: &NestedField) -> Result<&'a P>;
196    /// Get the list element partner from list partner.
197    fn list_element_partner<'a>(&self, list_partner: &'a P) -> Result<&'a P>;
198    /// Get the map key partner from map partner.
199    fn map_key_partner<'a>(&self, map_partner: &'a P) -> Result<&'a P>;
200    /// Get the map value partner from map partner.
201    fn map_value_partner<'a>(&self, map_partner: &'a P) -> Result<&'a P>;
202}
203
204/// Visiting a type in post order.
205pub(crate) fn visit_type_with_partner<P, V: SchemaWithPartnerVisitor<P>, A: PartnerAccessor<P>>(
206    r#type: &Type,
207    partner: &P,
208    visitor: &mut V,
209    accessor: &A,
210) -> Result<V::T> {
211    match r#type {
212        Type::Primitive(p) => visitor.primitive(p, partner),
213        Type::List(list) => {
214            let list_element_partner = accessor.list_element_partner(partner)?;
215            visitor.before_list_element(&list.element_field, list_element_partner)?;
216            let element_results = visit_type_with_partner(
217                &list.element_field.field_type,
218                list_element_partner,
219                visitor,
220                accessor,
221            )?;
222            visitor.after_list_element(&list.element_field, list_element_partner)?;
223            visitor.list(list, partner, element_results)
224        }
225        Type::Map(map) => {
226            let key_partner = accessor.map_key_partner(partner)?;
227            visitor.before_map_key(&map.key_field, key_partner)?;
228            let key_result =
229                visit_type_with_partner(&map.key_field.field_type, key_partner, visitor, accessor)?;
230            visitor.after_map_key(&map.key_field, key_partner)?;
231
232            let value_partner = accessor.map_value_partner(partner)?;
233            visitor.before_map_value(&map.value_field, value_partner)?;
234            let value_result = visit_type_with_partner(
235                &map.value_field.field_type,
236                value_partner,
237                visitor,
238                accessor,
239            )?;
240            visitor.after_map_value(&map.value_field, value_partner)?;
241
242            visitor.map(map, partner, key_result, value_result)
243        }
244        Type::Struct(s) => visit_struct_with_partner(s, partner, visitor, accessor),
245    }
246}
247
248/// Visit struct type in post order.
249pub fn visit_struct_with_partner<P, V: SchemaWithPartnerVisitor<P>, A: PartnerAccessor<P>>(
250    s: &StructType,
251    partner: &P,
252    visitor: &mut V,
253    accessor: &A,
254) -> Result<V::T> {
255    let mut results = Vec::with_capacity(s.fields().len());
256    for field in s.fields() {
257        let field_partner = accessor.field_partner(partner, field)?;
258        visitor.before_struct_field(field, field_partner)?;
259        let result = visit_type_with_partner(&field.field_type, field_partner, visitor, accessor)?;
260        visitor.after_struct_field(field, field_partner)?;
261        let result = visitor.field(field, field_partner, result)?;
262        results.push(result);
263    }
264
265    visitor.r#struct(s, partner, results)
266}
267
268/// Visit schema in post order.
269pub fn visit_schema_with_partner<P, V: SchemaWithPartnerVisitor<P>, A: PartnerAccessor<P>>(
270    schema: &Schema,
271    partner: &P,
272    visitor: &mut V,
273    accessor: &A,
274) -> Result<V::T> {
275    let result = visit_struct_with_partner(
276        &schema.r#struct,
277        accessor.struct_partner(partner)?,
278        visitor,
279        accessor,
280    )?;
281    visitor.schema(schema, partner, result)
282}