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
//! Typed patterns. [`crate::view_pattern`] and [`crate::api_pattern`]
//! check a pattern at compile time and generate the struct of its params.

use std::fmt;

/// The params of a view pattern, generated by [`crate::view_pattern`].
pub trait ViewPatternParams: Sized + Send + 'static {
	/// The pattern that these params belong to, as written.
	const PATTERN: &'static str;

	/// Constructs the params from the selected pattern's decoded match.
	#[doc(hidden)]
	fn from_decoded_match(decoded_match: DecodedMatch) -> Result<Self, MissingParamError>;

	/// Returns the params as a decoded match, for a page target.
	#[doc(hidden)]
	fn into_decoded_match(self) -> DecodedMatch;
}

/// The params of an API endpoint, generated by [`crate::api_pattern`].
pub trait ApiPatternParams: Sized + Send + 'static {
	/// The API pattern that these params belong to, as written.
	const PATTERN: &'static str;

	/// Constructs the params from the selected endpoint's decoded match.
	#[doc(hidden)]
	fn from_decoded_match(decoded_match: DecodedMatch) -> Result<Self, MissingParamError>;

	/// Returns the params as a decoded match, for an endpoint target.
	#[doc(hidden)]
	fn into_decoded_match(self) -> DecodedMatch;
}

/// The decoded params and splat values of one matched pattern.
#[doc(hidden)]
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct DecodedMatch {
	pub(crate) params: Vec<(String, String)>,
	pub(crate) splat_values: Vec<String>,
}

impl DecodedMatch {
	/// Constructs a decoded match from params and splat values.
	pub fn new(params: Vec<(String, String)>, splat_values: Vec<String>) -> Self {
		Self {
			params,
			splat_values,
		}
	}

	/// Removes and returns one param.
	pub fn take_param(&mut self, name: &'static str) -> Result<String, MissingParamError> {
		let index = self
			.params
			.iter()
			.position(|(param_name, _)| param_name == name)
			.ok_or(MissingParamError { name })?;
		Ok(self.params.swap_remove(index).1)
	}

	/// Removes and returns the splat values.
	pub fn take_splat_values(&mut self) -> Vec<String> {
		std::mem::take(&mut self.splat_values)
	}
}

/// A params struct names a param that its matched pattern does not have.
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MissingParamError {
	name: &'static str,
}

impl fmt::Display for MissingParamError {
	fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
		write!(
			formatter,
			"the matched pattern has no {:?} param",
			self.name
		)
	}
}

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