Skip to main content

rivet_error/
schema.rs

1use crate::error::{RivetError, RivetErrorKind};
2use serde::Serialize;
3use std::marker::PhantomData;
4
5/// Private marker type that proves an error was created through the macro
6#[derive(Debug)]
7pub struct MacroMarker {
8	pub _private: (),
9}
10
11/// Can only be created through the rivet_error macro.
12#[derive(Debug)]
13pub struct RivetErrorSchema {
14	pub group: &'static str,
15	pub code: &'static str,
16	pub default_message: &'static str,
17	#[allow(dead_code)]
18	pub meta_type: Option<&'static str>,
19	/// Private marker that ensures this was created by the macro
20	pub _macro_marker: MacroMarker,
21}
22
23/// Can only be created through the rivet_error macro.
24#[derive(Debug)]
25pub struct RivetErrorSchemaWithMeta<T> {
26	pub schema: RivetErrorSchema,
27	pub message_fn: fn(&T) -> String,
28	pub _phantom: PhantomData<T>,
29}
30
31impl RivetErrorSchema {
32	/// Internal constructor for built-in errors only (like INTERNAL_ERROR)
33	#[doc(hidden)]
34	pub(crate) const fn __internal_new(
35		group: &'static str,
36		code: &'static str,
37		message: &'static str,
38	) -> Self {
39		Self {
40			group,
41			code,
42			default_message: message,
43			meta_type: None,
44			_macro_marker: MacroMarker { _private: () },
45		}
46	}
47
48	/// Builds an anyhow::Error from this schema
49	pub fn build(&'static self) -> anyhow::Error {
50		let error = RivetError {
51			kind: RivetErrorKind::Static(self),
52			meta: None,
53			message: None,
54			actor: None,
55		};
56		anyhow::Error::new(error)
57	}
58
59	pub(crate) fn build_internal(&'static self, error: &anyhow::Error) -> RivetError {
60		RivetError::build_internal(error)
61	}
62}
63
64impl<T: Serialize> RivetErrorSchemaWithMeta<T> {
65	/// Builds an anyhow::Error from this schema with the provided metadata
66	pub fn build_with(&'static self, meta: T) -> anyhow::Error {
67		let message = (self.message_fn)(&meta);
68		let meta_json = serde_json::value::to_raw_value(&meta).ok();
69
70		let error = RivetError {
71			kind: RivetErrorKind::Static(&self.schema),
72			meta: meta_json,
73			message: Some(message),
74			actor: None,
75		};
76		anyhow::Error::new(error)
77	}
78}
79
80impl From<&'static RivetErrorSchema> for RivetError {
81	fn from(value: &'static RivetErrorSchema) -> Self {
82		RivetError {
83			kind: RivetErrorKind::Static(value),
84			meta: None,
85			message: None,
86			actor: None,
87		}
88	}
89}