vorma 0.86.0-pre.4

Rust-first full-stack web framework: typed views and resources, generated TypeScript contracts, and a Vite-integrated frontend.
Documentation
//! A check that a value has no non-finite floats. JSON has no form for NaN or
//! an infinity, and serde_json writes them as `null`, so a float field would
//! reach the browser as `null` while its generated TypeScript type says
//! `number`. Vorma refuses such a value instead of sending it.

use std::fmt;

use serde::ser::{self, Serialize};

/// The value contains NaN or an infinity.
#[derive(Debug)]
pub(crate) struct NonFiniteFloat;

impl fmt::Display for NonFiniteFloat {
	fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
		formatter.write_str("it contains NaN or an infinity, which JSON cannot represent")
	}
}

impl std::error::Error for NonFiniteFloat {}

/// A failure of the check. A value's own serialization failure also arrives
/// here; the check ignores it, because the serialization that follows reports
/// it with its own message.
#[derive(Debug)]
pub(crate) enum CheckError {
	NonFiniteFloat,
	Other,
}

impl fmt::Display for CheckError {
	fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
		match self {
			Self::NonFiniteFloat => NonFiniteFloat.fmt(formatter),
			Self::Other => formatter.write_str("the value cannot be serialized"),
		}
	}
}

impl std::error::Error for CheckError {}

impl ser::Error for CheckError {
	fn custom<T: fmt::Display>(_message: T) -> Self {
		Self::Other
	}
}

/// Fails when `value` contains a non-finite `f32` or `f64` at any depth.
pub(crate) fn check_finite_floats<Value: Serialize + ?Sized>(
	value: &Value,
) -> Result<(), NonFiniteFloat> {
	match value.serialize(FiniteCheck) {
		Err(CheckError::NonFiniteFloat) => Err(NonFiniteFloat),
		Ok(()) | Err(CheckError::Other) => Ok(()),
	}
}

struct FiniteCheck;

fn check_float(finite: bool) -> Result<(), CheckError> {
	if finite {
		Ok(())
	} else {
		Err(CheckError::NonFiniteFloat)
	}
}

impl ser::Serializer for FiniteCheck {
	type Ok = ();
	type Error = CheckError;
	type SerializeSeq = Self;
	type SerializeTuple = Self;
	type SerializeTupleStruct = Self;
	type SerializeTupleVariant = Self;
	type SerializeMap = Self;
	type SerializeStruct = Self;
	type SerializeStructVariant = Self;

	fn serialize_bool(self, _value: bool) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_i8(self, _value: i8) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_i16(self, _value: i16) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_i32(self, _value: i32) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_i64(self, _value: i64) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_i128(self, _value: i128) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_u8(self, _value: u8) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_u16(self, _value: u16) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_u32(self, _value: u32) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_u64(self, _value: u64) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_u128(self, _value: u128) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_f32(self, value: f32) -> Result<(), CheckError> {
		check_float(value.is_finite())
	}

	fn serialize_f64(self, value: f64) -> Result<(), CheckError> {
		check_float(value.is_finite())
	}

	fn serialize_char(self, _value: char) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_str(self, _value: &str) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_bytes(self, _value: &[u8]) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_none(self) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_some<Value: Serialize + ?Sized>(self, value: &Value) -> Result<(), CheckError> {
		value.serialize(self)
	}

	fn serialize_unit(self) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_unit_struct(self, _name: &'static str) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_unit_variant(
		self,
		_name: &'static str,
		_index: u32,
		_variant: &'static str,
	) -> Result<(), CheckError> {
		Ok(())
	}

	fn serialize_newtype_struct<Value: Serialize + ?Sized>(
		self,
		_name: &'static str,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(self)
	}

	fn serialize_newtype_variant<Value: Serialize + ?Sized>(
		self,
		_name: &'static str,
		_index: u32,
		_variant: &'static str,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(self)
	}

	fn serialize_seq(self, _length: Option<usize>) -> Result<Self, CheckError> {
		Ok(self)
	}

	fn serialize_tuple(self, _length: usize) -> Result<Self, CheckError> {
		Ok(self)
	}

	fn serialize_tuple_struct(
		self,
		_name: &'static str,
		_length: usize,
	) -> Result<Self, CheckError> {
		Ok(self)
	}

	fn serialize_tuple_variant(
		self,
		_name: &'static str,
		_index: u32,
		_variant: &'static str,
		_length: usize,
	) -> Result<Self, CheckError> {
		Ok(self)
	}

	fn serialize_map(self, _length: Option<usize>) -> Result<Self, CheckError> {
		Ok(self)
	}

	fn serialize_struct(self, _name: &'static str, _length: usize) -> Result<Self, CheckError> {
		Ok(self)
	}

	fn serialize_struct_variant(
		self,
		_name: &'static str,
		_index: u32,
		_variant: &'static str,
		_length: usize,
	) -> Result<Self, CheckError> {
		Ok(self)
	}
}

impl ser::SerializeSeq for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_element<Value: Serialize + ?Sized>(
		&mut self,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}

impl ser::SerializeTuple for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_element<Value: Serialize + ?Sized>(
		&mut self,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}

impl ser::SerializeTupleStruct for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_field<Value: Serialize + ?Sized>(
		&mut self,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}

impl ser::SerializeTupleVariant for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_field<Value: Serialize + ?Sized>(
		&mut self,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}

impl ser::SerializeMap for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_key<Key: Serialize + ?Sized>(&mut self, key: &Key) -> Result<(), CheckError> {
		key.serialize(FiniteCheck)
	}

	fn serialize_value<Value: Serialize + ?Sized>(
		&mut self,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}

impl ser::SerializeStruct for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_field<Value: Serialize + ?Sized>(
		&mut self,
		_key: &'static str,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}

impl ser::SerializeStructVariant for FiniteCheck {
	type Ok = ();
	type Error = CheckError;

	fn serialize_field<Value: Serialize + ?Sized>(
		&mut self,
		_key: &'static str,
		value: &Value,
	) -> Result<(), CheckError> {
		value.serialize(FiniteCheck)
	}

	fn end(self) -> Result<(), CheckError> {
		Ok(())
	}
}