chuchi_postgres/macros/
mod.rs

1#[doc(hidden)]
2pub use bytes::BytesMut;
3#[doc(hidden)]
4pub use postgres_types::{FromSql, IsNull, ToSql, Type, to_sql_checked};
5
6/// ## Example
7/// ```
8/// # use chuchi_postgres::try2;
9///
10/// fn mul(maybe_num: Option<i32>) -> Result<Option<i32>, &'static str> {
11/// 	let x = try2!(maybe_num);
12///
13/// 	x.checked_mul(2)
14/// 		.map(Some)
15/// 		.ok_or("overflow")
16/// }
17/// ```
18#[macro_export]
19macro_rules! try2 {
20	($exp:expr) => {
21		match $exp {
22			Some(o) => o,
23			None => return Ok(None),
24		}
25	};
26}
27
28/// ## Example
29/// ```
30/// # use chuchi_postgres::try_vec;
31///
32/// fn add(maybe_vec: Option<Vec<i32>>) -> Result<Vec<i32>, &'static str> {
33/// 	let v = try_vec!(maybe_vec);
34///
35/// 	Ok(v.into_iter().map(|x| x + 1).collect())
36/// }
37/// ```
38#[macro_export]
39macro_rules! try_vec {
40	($exp:expr) => {
41		match $exp {
42			Some(o) => o,
43			None => return Ok(vec![]),
44		}
45	};
46}
47
48/// ## Example
49/// ```
50/// use chuchi_postgres::enum_u16;
51/// enum_u16! {
52/// 	#[derive(Debug)]
53/// 	pub enum SiteRaw {
54/// 		FrameUser = 10,
55/// 		Admin = 20,
56/// 		App = 30
57/// 	}
58/// }
59/// ```
60#[macro_export]
61macro_rules! enum_u16 {
62	($(#[$metas:meta])* $($pub:ident)? enum $name:ident {
63		$($opt:ident = $num:expr),*
64	}) => {
65		$(#[$metas])*
66		#[repr(u16)]
67		$($pub)? enum $name {
68			$($opt = $num),*
69		}
70
71		impl $name {
72			pub fn as_u16(&self) -> u16 {
73				match self {
74					$(Self::$opt => $num),*
75				}
76			}
77
78			pub fn from_u16(
79				num: u16
80			) -> std::result::Result<Self, &'static str> {
81				match num {
82					$($num => Ok(Self::$opt)),*,
83					_ => Err(stringify!(could not parse u16 to $name))
84				}
85			}
86		}
87
88		impl $crate::table::column::ColumnType for $name {
89			fn column_kind() -> $crate::table::column::ColumnKind {
90				$crate::table::column::ColumnKind::I32
91			}
92		}
93
94		impl $crate::macros::ToSql for $name {
95			fn to_sql(
96				&self,
97				ty: &$crate::macros::Type,
98				buf: &mut $crate::macros::BytesMut
99			) -> std::result::Result<$crate::macros::IsNull, Box<dyn std::error::Error + Sync + Send>> {
100				let val = self.as_u16() as i32;
101
102				val.to_sql(ty, buf)
103			}
104
105			fn accepts(ty: &$crate::macros::Type) -> bool {
106				<i32 as $crate::macros::ToSql>::accepts(ty)
107			}
108
109			$crate::macros::to_sql_checked!();
110		}
111
112		impl<'a> $crate::macros::FromSql<'a> for $name {
113			fn from_sql(
114				ty: &$crate::macros::Type,
115				buf: &'a [u8]
116			) -> std::result::Result<Self, Box<dyn std::error::Error + Sync + Send>> {
117				let num = <i32 as $crate::macros::FromSql>::from_sql(ty, buf)?;
118				num.try_into()
119					.map_err(|_| "i32 to u16 conversion failed")
120					.and_then(Self::from_u16)
121					.map_err(|m| m.into())
122			}
123
124			fn accepts(ty: &$crate::macros::Type) -> bool {
125				<i32 as $crate::macros::FromSql>::accepts(ty)
126			}
127		}
128
129		impl $crate::filter::ParamData for $name {
130			fn is_null(&self) -> bool {
131				false
132			}
133		}
134	};
135}