Skip to main content

apache_avro/serde/ser_schema/
tuple.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 std::{borrow::Borrow, io::Write};
19
20use serde::{
21    Serialize,
22    ser::{SerializeTuple, SerializeTupleStruct, SerializeTupleVariant},
23};
24
25use super::{Config, SchemaAwareSerializer, union::UnionSerializer};
26use crate::{
27    Error, Schema,
28    error::Details,
29    schema::{RecordSchema, UnionSchema},
30};
31
32#[expect(
33    private_interfaces,
34    reason = "One{,Union}TupleSerializer should not be used directly"
35)]
36pub enum TupleSerializer<'s, 'w, W: Write, S: Borrow<Schema>> {
37    Unit(usize),
38    One(OneTupleSerializer<'s, 'w, W, S>),
39    /// This exists because we can't create a `&Schema::Union` from a `&UnionSchema`
40    OneUnion(OneUnionTupleSerializer<'s, 'w, W, S>),
41    Many(ManyTupleSerializer<'s, 'w, W, S>),
42}
43
44impl<'s, 'w, W: Write, S: Borrow<Schema>> TupleSerializer<'s, 'w, W, S> {
45    pub fn unit(bytes_written: Option<usize>) -> Self {
46        Self::Unit(bytes_written.unwrap_or(0))
47    }
48
49    pub fn one(
50        writer: &'w mut W,
51        schema: &'s Schema,
52        config: Config<'s, S>,
53        bytes_written: Option<usize>,
54    ) -> Self {
55        Self::One(OneTupleSerializer::new(
56            writer,
57            schema,
58            config,
59            bytes_written,
60        ))
61    }
62
63    pub fn one_union(writer: &'w mut W, union: &'s UnionSchema, config: Config<'s, S>) -> Self {
64        Self::OneUnion(OneUnionTupleSerializer::new(writer, union, config))
65    }
66
67    pub fn many(
68        writer: &'w mut W,
69        schema: &'s RecordSchema,
70        config: Config<'s, S>,
71        bytes_written: Option<usize>,
72    ) -> Self {
73        Self::Many(ManyTupleSerializer::new(
74            writer,
75            schema,
76            config,
77            bytes_written,
78        ))
79    }
80}
81
82impl<'s, 'w, W: Write, S: Borrow<Schema>> SerializeTuple for TupleSerializer<'s, 'w, W, S> {
83    type Ok = usize;
84    type Error = Error;
85
86    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
87    where
88        T: ?Sized + Serialize,
89    {
90        match self {
91            TupleSerializer::Unit(_) => Err(Error::new(Details::SerializeValueWithSchema {
92                value_type: "tuple",
93                value: "Expected no elements for the unit tuple".into(),
94                schema: Schema::Null,
95            })),
96            TupleSerializer::One(one) => one.serialize_element(value),
97            TupleSerializer::OneUnion(one) => one.serialize_element(value),
98            TupleSerializer::Many(many) => many.serialize_element(value),
99        }
100    }
101
102    fn end(self) -> Result<Self::Ok, Self::Error> {
103        match self {
104            TupleSerializer::Unit(bytes_written) => Ok(bytes_written),
105            TupleSerializer::One(one) => one.end(),
106            TupleSerializer::OneUnion(one) => one.end(),
107            TupleSerializer::Many(many) => SerializeTuple::end(many),
108        }
109    }
110}
111
112pub struct ManyTupleSerializer<'s, 'w, W: Write, S: Borrow<Schema>> {
113    writer: &'w mut W,
114    schema: &'s RecordSchema,
115    config: Config<'s, S>,
116    field_position: usize,
117    bytes_written: usize,
118}
119
120impl<'s, 'w, W: Write, S: Borrow<Schema>> ManyTupleSerializer<'s, 'w, W, S> {
121    pub fn new(
122        writer: &'w mut W,
123        schema: &'s RecordSchema,
124        config: Config<'s, S>,
125        bytes_written: Option<usize>,
126    ) -> Self {
127        Self {
128            writer,
129            schema,
130            config,
131            field_position: 0,
132            bytes_written: bytes_written.unwrap_or(0),
133        }
134    }
135}
136
137impl<'s, 'w, W: Write, S: Borrow<Schema>> SerializeTuple for ManyTupleSerializer<'s, 'w, W, S> {
138    type Ok = usize;
139    type Error = Error;
140
141    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
142    where
143        T: ?Sized + Serialize,
144    {
145        let schema = &self
146            .schema
147            .fields
148            .get(self.field_position)
149            .ok_or_else(|| Details::SerializeRecordUnknownFieldIndex {
150                position: self.field_position,
151                schema: self.schema.clone(),
152            })?
153            .schema;
154        self.bytes_written += value.serialize(SchemaAwareSerializer::new(
155            self.writer,
156            schema,
157            self.config,
158        )?)?;
159        self.field_position += 1;
160        Ok(())
161    }
162
163    fn end(self) -> Result<Self::Ok, Self::Error> {
164        if self.field_position != self.schema.fields.len() {
165            Err(Details::SerializeTupleMissingElements {
166                position: self.field_position,
167                total_elements: self.schema.fields.len(),
168            }
169            .into())
170        } else {
171            Ok(self.bytes_written)
172        }
173    }
174}
175
176impl<'s, 'w, W: Write, S: Borrow<Schema>> SerializeTupleStruct
177    for ManyTupleSerializer<'s, 'w, W, S>
178{
179    type Ok = usize;
180    type Error = Error;
181
182    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
183    where
184        T: ?Sized + Serialize,
185    {
186        SerializeTuple::serialize_element(self, value)
187    }
188
189    fn end(self) -> Result<Self::Ok, Self::Error> {
190        SerializeTuple::end(self)
191    }
192}
193
194impl<'s, 'w, W: Write, S: Borrow<Schema>> SerializeTupleVariant
195    for ManyTupleSerializer<'s, 'w, W, S>
196{
197    type Ok = usize;
198    type Error = Error;
199
200    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
201    where
202        T: ?Sized + Serialize,
203    {
204        SerializeTuple::serialize_element(self, value)
205    }
206
207    fn end(self) -> Result<Self::Ok, Self::Error> {
208        SerializeTuple::end(self)
209    }
210}
211
212struct OneTupleSerializer<'s, 'w, W: Write, S: Borrow<Schema>> {
213    writer: &'w mut W,
214    schema: &'s Schema,
215    config: Config<'s, S>,
216    bytes_written: usize,
217}
218
219impl<'s, 'w, W: Write, S: Borrow<Schema>> OneTupleSerializer<'s, 'w, W, S> {
220    pub fn new(
221        writer: &'w mut W,
222        schema: &'s Schema,
223        config: Config<'s, S>,
224        bytes_written: Option<usize>,
225    ) -> Self {
226        Self {
227            writer,
228            schema,
229            config,
230            bytes_written: bytes_written.unwrap_or(0),
231        }
232    }
233}
234
235impl<'s, 'w, W: Write, S: Borrow<Schema>> SerializeTuple for OneTupleSerializer<'s, 'w, W, S> {
236    type Ok = usize;
237    type Error = Error;
238
239    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
240    where
241        T: ?Sized + Serialize,
242    {
243        match self.schema {
244            Schema::Union(union) => {
245                self.bytes_written +=
246                    value.serialize(UnionSerializer::new(self.writer, union, self.config))?;
247            }
248            schema => {
249                self.bytes_written += value.serialize(SchemaAwareSerializer::new(
250                    self.writer,
251                    schema,
252                    self.config,
253                )?)?;
254            }
255        }
256        Ok(())
257    }
258
259    fn end(self) -> Result<Self::Ok, Self::Error> {
260        Ok(self.bytes_written)
261    }
262}
263
264struct OneUnionTupleSerializer<'s, 'w, W: Write, S: Borrow<Schema>> {
265    writer: &'w mut W,
266    union: &'s UnionSchema,
267    config: Config<'s, S>,
268    bytes_written: usize,
269}
270
271impl<'s, 'w, W: Write, S: Borrow<Schema>> OneUnionTupleSerializer<'s, 'w, W, S> {
272    pub fn new(writer: &'w mut W, union: &'s UnionSchema, config: Config<'s, S>) -> Self {
273        Self {
274            writer,
275            union,
276            config,
277            bytes_written: 0,
278        }
279    }
280}
281
282impl<'s, 'w, W: Write, S: Borrow<Schema>> SerializeTuple for OneUnionTupleSerializer<'s, 'w, W, S> {
283    type Ok = usize;
284    type Error = Error;
285
286    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
287    where
288        T: ?Sized + Serialize,
289    {
290        self.bytes_written +=
291            value.serialize(UnionSerializer::new(self.writer, self.union, self.config))?;
292        Ok(())
293    }
294
295    fn end(self) -> Result<Self::Ok, Self::Error> {
296        Ok(self.bytes_written)
297    }
298}