surrealdb-sql 1.1.0

Full type definitions for the SurrealQL query language
Documentation
use crate::err::Error;
use crate::value::serde::ser;
use crate::Expression;
use crate::Operator;
use crate::Value;
use ser::Serializer as _;
use serde::ser::Error as _;
use serde::ser::Impossible;
use serde::ser::Serialize;

pub(super) struct Serializer;

impl ser::Serializer for Serializer {
	type Ok = Expression;
	type Error = Error;

	type SerializeSeq = Impossible<Expression, Error>;
	type SerializeTuple = Impossible<Expression, Error>;
	type SerializeTupleStruct = Impossible<Expression, Error>;
	type SerializeTupleVariant = Impossible<Expression, Error>;
	type SerializeMap = Impossible<Expression, Error>;
	type SerializeStruct = Impossible<Expression, Error>;
	type SerializeStructVariant = SerializeExpression;

	const EXPECTED: &'static str = "an enum `Expression`";

	#[inline]
	fn serialize_struct_variant(
		self,
		name: &'static str,
		_variant_index: u32,
		variant: &'static str,
		_len: usize,
	) -> Result<Self::SerializeStructVariant, Self::Error> {
		debug_assert_eq!(name, crate::expression::TOKEN);
		match variant {
			"Unary" => Ok(SerializeExpression::Unary(Default::default())),
			"Binary" => Ok(SerializeExpression::Binary(Default::default())),
			_ => Err(Error::custom(format!("unexpected `Expression::{name}`"))),
		}
	}
}

pub(super) enum SerializeExpression {
	Unary(SerializeUnary),
	Binary(SerializeBinary),
}

impl serde::ser::SerializeStructVariant for SerializeExpression {
	type Ok = Expression;
	type Error = Error;

	fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
	where
		T: ?Sized + Serialize,
	{
		match self {
			Self::Unary(unary) => unary.serialize_field(key, value),
			Self::Binary(binary) => binary.serialize_field(key, value),
		}
	}

	fn end(self) -> Result<Self::Ok, Error> {
		match self {
			Self::Unary(unary) => unary.end(),
			Self::Binary(binary) => binary.end(),
		}
	}
}

#[derive(Default)]
pub(super) struct SerializeUnary {
	o: Option<Operator>,
	v: Option<Value>,
}

impl serde::ser::SerializeStructVariant for SerializeUnary {
	type Ok = Expression;
	type Error = Error;

	fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
	where
		T: ?Sized + Serialize,
	{
		match key {
			"o" => {
				self.o = Some(value.serialize(ser::operator::Serializer.wrap())?);
			}
			"v" => {
				self.v = Some(value.serialize(ser::value::Serializer.wrap())?);
			}
			key => {
				return Err(Error::custom(format!(
					"unexpected field `Expression::Unary{{{key}}}`"
				)));
			}
		}
		Ok(())
	}

	fn end(self) -> Result<Self::Ok, Error> {
		match (self.o, self.v) {
			(Some(o), Some(v)) => Ok(Expression::Unary {
				o,
				v,
			}),
			_ => Err(Error::custom("`Expression::Unary` missing required field(s)")),
		}
	}
}

#[derive(Default)]
pub(super) struct SerializeBinary {
	l: Option<Value>,
	o: Option<Operator>,
	r: Option<Value>,
}

impl serde::ser::SerializeStructVariant for SerializeBinary {
	type Ok = Expression;
	type Error = Error;

	fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
	where
		T: ?Sized + Serialize,
	{
		match key {
			"l" => {
				self.l = Some(value.serialize(ser::value::Serializer.wrap())?);
			}
			"o" => {
				self.o = Some(value.serialize(ser::operator::Serializer.wrap())?);
			}
			"r" => {
				self.r = Some(value.serialize(ser::value::Serializer.wrap())?);
			}
			key => {
				return Err(Error::custom(format!(
					"unexpected field `Expression::Binary{{{key}}}`"
				)));
			}
		}
		Ok(())
	}

	fn end(self) -> Result<Self::Ok, Error> {
		match (self.l, self.o, self.r) {
			(Some(l), Some(o), Some(r)) => Ok(Expression::Binary {
				l,
				o,
				r,
			}),
			_ => Err(Error::custom("`Expression::Binary` missing required field(s)")),
		}
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use serde::Serialize;

	#[test]
	fn default() {
		let expression = Expression::default();
		let serialized = expression.serialize(Serializer.wrap()).unwrap();
		assert_eq!(expression, serialized);
	}

	#[test]
	fn unary() {
		let expression = Expression::Unary {
			o: Operator::Not,
			v: "Bar".into(),
		};
		let serialized = expression.serialize(Serializer.wrap()).unwrap();
		assert_eq!(expression, serialized);
	}

	#[test]
	fn foo_equals_bar() {
		let expression = Expression::Binary {
			l: "foo".into(),
			o: Operator::Equal,
			r: "Bar".into(),
		};
		let serialized = expression.serialize(Serializer.wrap()).unwrap();
		assert_eq!(expression, serialized);
	}
}