serde_avro_fast 2.1.0

An idiomatic implementation of serde/avro (de)serialization
Documentation
use super::*;

pub struct SerializeSeqOrTupleOrTupleStruct<'r, 'c, 's, W> {
	kind: Kind<'r, 'c, 's, W>,
}

enum Kind<'r, 'c, 's, W> {
	Array {
		block_writer: BlockWriter<'r, 'c, 's, W>,
		elements_schema: &'s SchemaNode<'s>,
	},
	Duration {
		serializer_state: &'r mut SerializerState<'c, 's, W>,
		n_values: u8,
	},
	BufferedBytes {
		serializer_state: &'r mut SerializerState<'c, 's, W>,
		buffer: Vec<u8>,
	},
	Fixed {
		serializer_state: &'r mut SerializerState<'c, 's, W>,
		expected_len: usize,
	},
	Finished,
}

impl<'r, 'c, 's, W: Write> SerializeSeqOrTupleOrTupleStruct<'r, 'c, 's, W> {
	pub(super) fn array(
		block_writer: BlockWriter<'r, 'c, 's, W>,
		elements_schema: &'s SchemaNode<'s>,
	) -> Self {
		Self {
			kind: Kind::Array {
				block_writer,
				elements_schema,
			},
		}
	}

	pub(super) fn duration(serializer_state: &'r mut SerializerState<'c, 's, W>) -> Self {
		Self {
			kind: Kind::Duration {
				serializer_state,
				n_values: 0,
			},
		}
	}

	pub(crate) fn buffered_bytes(state: &'r mut SerializerState<'c, 's, W>) -> Self {
		Self {
			kind: Kind::BufferedBytes {
				buffer: state
					.config
					.buffers
					.field_reordering_buffers
					.pop()
					.inspect(|v| assert!(v.is_empty()))
					.unwrap_or_else(Vec::new),
				serializer_state: state,
			},
		}
	}

	pub(crate) fn bytes(
		state: &'r mut SerializerState<'c, 's, W>,
		len: usize,
	) -> Result<Self, SerError> {
		state
			.writer
			.write_varint::<i64>(len.try_into().map_err(|_| {
				SerError::new(
					"Buffer len does not fit i64 for encoding as length-delimited field size",
				)
			})?)
			.map_err(SerError::io)?;
		Ok(Self::fixed(state, len))
	}

	pub(crate) fn fixed(state: &'r mut SerializerState<'c, 's, W>, expected_len: usize) -> Self {
		Self {
			kind: Kind::Fixed {
				serializer_state: state,
				expected_len,
			},
		}
	}

	fn serialize_element<T>(&mut self, value: &T) -> Result<(), SerError>
	where
		T: Serialize + ?Sized,
	{
		match self.kind {
			Kind::Array {
				ref mut block_writer,
				elements_schema,
			} => {
				block_writer.signal_next_record()?;
				value.serialize(DatumSerializer {
					state: block_writer.state,
					schema_node: elements_schema,
				})
			}
			Kind::Duration {
				ref mut serializer_state,
				ref mut n_values,
			} => {
				if *n_values >= 3 {
					Err(duration_seq_len_incorrect())
				} else {
					let val =
						value.serialize(super::extract_for_duration::ExtractU32ForDuration)?;
					serializer_state
						.writer
						.write_all(&val.to_le_bytes())
						.map_err(SerError::io)?;
					*n_values += 1;
					Ok(())
				}
			}
			Kind::BufferedBytes { ref mut buffer, .. } => {
				buffer.push(value.serialize(ExtractU8Serializer)?);
				Ok(())
			}
			Kind::Fixed {
				ref mut serializer_state,
				ref mut expected_len,
			} => {
				match (*expected_len).checked_sub(1) {
					Some(n) => *expected_len = n,
					None => {
						return Err(SerError::new(
							"Advertised/Fixed length exceeded for serialization as Fixed/Bytes",
						))
					}
				}
				serializer_state
					.writer
					.write_all(&[value.serialize(ExtractU8Serializer)?])
					.map_err(SerError::io)?;

				Ok(())
			}
			Kind::Finished => Err(should_not_be_finished()),
		}
	}

	fn end(mut self) -> Result<(), SerError> {
		match self.kind {
			Kind::Array { .. } => match std::mem::replace(&mut self.kind, Kind::Finished) {
				Kind::Array { block_writer, .. } => block_writer.end(),
				_ => unreachable!(),
			},
			Kind::Duration { n_values, .. } => {
				if n_values != 3 {
					Err(duration_seq_len_incorrect())
				} else {
					Ok(())
				}
			}
			Kind::BufferedBytes {
				ref mut serializer_state,
				ref buffer,
			} => serializer_state.write_length_delimited(buffer),
			Kind::Fixed { expected_len, .. } => {
				if expected_len != 0 {
					Err(SerError::new(
						"Advertised/Fixed length not reached for serialization as Fixed/Bytes",
					))
				} else {
					Ok(())
				}
			}
			Kind::Finished => Err(should_not_be_finished()),
		}
	}
}

impl<W> Drop for SerializeSeqOrTupleOrTupleStruct<'_, '_, '_, W> {
	fn drop(&mut self) {
		if let Kind::BufferedBytes {
			serializer_state,
			mut buffer,
		} = std::mem::replace(&mut self.kind, Kind::Finished)
		{
			if buffer.capacity() > 0 {
				buffer.clear();
				serializer_state
					.config
					.buffers
					.field_reordering_buffers
					.push(buffer);
			}
		}
	}
}

pub(super) fn duration_seq_len_incorrect() -> SerError {
	SerError::new("seq/tuple can indeed be serialized as Duration, but only if it's of length 3")
}

fn should_not_be_finished() -> SerError {
	SerError::new(
		"Internal serializer error: should not have state \
				Finished before `end()` is called",
	)
}

macro_rules! impl_serialize_seq_or_tuple {
	($($trait_: ident $f: ident,)+) => {
		$(
			impl<'r, 'c, 's, W: Write> $trait_ for SerializeSeqOrTupleOrTupleStruct<'r, 'c, 's, W> {
				type Ok = ();
				type Error = SerError;

				fn $f<T>(&mut self, value: &T) -> Result<(), Self::Error>
				where
					T: Serialize + ?Sized,
				{
					self.serialize_element(value)
				}

				fn end(self) -> Result<Self::Ok, Self::Error> {
					self.end()
				}
			}
		)*
	};
}
impl_serialize_seq_or_tuple! {
	SerializeSeq serialize_element,
	SerializeTuple serialize_element,
	SerializeTupleStruct serialize_field,
	SerializeTupleVariant serialize_field,
}

struct ExtractU8Serializer;
impl Serializer for ExtractU8Serializer {
	type Ok = u8;
	type Error = SerError;

	fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds i8->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds i16->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds i32->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds i64->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
		Ok(v)
	}

	fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds u16->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds u32->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds u64->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds i128->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
		v.try_into().map_err(|_| {
			SerError::new(
				"Out of bounds u128->u8 element for sequence\
					serialization as Fixed/Bytes",
			)
		})
	}

	serde_serializer_quick_unsupported::serializer_unsupported! {
		err = (SerError::new("Elements should be u8-like for serialization as Fixed/Bytes"));
		bool f32 f64 char str bytes none some unit unit_struct
		unit_variant newtype_struct newtype_variant seq tuple tuple_struct tuple_variant map struct
		struct_variant
	}
}