Skip to content

Instantly share code, notes, and snippets.

@hbina
Created May 26, 2022 05:38
Show Gist options
  • Select an option

  • Save hbina/293c6d6ceca89b6bf3e4ed6966161c6c to your computer and use it in GitHub Desktop.

Select an option

Save hbina/293c6d6ceca89b6bf3e4ed6966161c6c to your computer and use it in GitHub Desktop.
Rust macro_rules to generate as_str, from_str, sqlx::Encode, sqlx::Decode for enums
#[macro_export]
macro_rules! impl_enum_asfrom_str {
($name:ident, $($next_variant:ident),+) => {
#[derive(::std::clone::Clone, Copy, Debug, Deserialize, Serialize)]
#[allow(clippy::upper_case_acronyms)]
#[allow(non_camel_case_types)]
pub enum $name {
$($next_variant),+
}
impl $name {
pub fn as_str(&self) -> &'static str {
match self {
$($name::$next_variant => stringify!($next_variant)),+
}
}
}
impl ::std::str::FromStr for $name {
type Err = String;
fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
match s {
$(stringify!($next_variant) => Ok($name::$next_variant)),+,
_ => Err(format!("Cannot convert '{}' into an enum variant of '{}'", s, stringify!($name)))
}
}
}
impl ::sqlx::Type<sqlx::Postgres> for $name {
fn type_info() -> ::sqlx::postgres::PgTypeInfo {
::sqlx::postgres::PgTypeInfo::with_name("text")
}
}
impl<'r> ::sqlx::Decode<'r, ::sqlx::Postgres> for $name {
fn decode(value: ::sqlx::postgres::PgValueRef<'r>) -> ::std::result::Result<Self, sqlx::error::BoxDynError> {
let value: &'r str = ::sqlx::decode::Decode::decode(value)?;
Ok(<$name as ::std::str::FromStr>::from_str(value)?)
}
}
impl ::sqlx::encode::Encode<'_, ::sqlx::Postgres> for $name {
fn encode_by_ref(
&self,
buf: &mut ::sqlx::postgres::PgArgumentBuffer,
) -> ::sqlx::encode::IsNull {
let val = self.as_str();
::sqlx::encode::Encode::<'_, ::sqlx::Postgres>::encode(val, buf)
}
fn size_hint(&self) -> ::std::primitive::usize {
let val = self.as_str();
::sqlx::encode::Encode::<'_, ::sqlx::Postgres>::size_hint(&val)
}
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment