pub mod entities; pub mod repositories; use rusqlite::ToSql; use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef}; use std::fmt::{Display, Formatter}; use std::num::ParseIntError; use std::str::FromStr; macro_rules! id_impl { ($id_type:ty, $name:ident, $invalid:ident) => { #[derive(Clone, PartialEq, Eq, Debug, Hash, Copy, Ord, PartialOrd, Default)] pub struct $name(pub(crate) $id_type); pub const $invalid: $name = $name(0); impl FromStr for $name { type Err = ParseIntError; fn from_str(s: &str) -> Result { Ok($name(s.parse::<$id_type>()?)) } } impl From<$id_type> for $name { fn from(value: $id_type) -> Self { $name(value) } } impl From<$name> for $id_type { fn from(value: $name) -> Self { value.0 } } impl Display for $name { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl FromSql for $name { fn column_result(value: ValueRef<'_>) -> FromSqlResult { match value { ValueRef::Integer(i) => Ok($name(i as $id_type)), _ => Err(FromSqlError::InvalidType), } } } impl ToSql for $name { fn to_sql(&self) -> rusqlite::Result> { Ok(ToSqlOutput::from(self.0 as i64)) } } impl From<$name> for String { fn from(value: $name) -> Self { value.0.to_string() } } impl $name { pub(crate) fn is_valid(self) -> bool { self.0 != 0 } } }; } id_impl!(u32, Id, INVALID_ID); id_impl!(u16, SmallId, INVALID_SMALL_ID); impl From for Id { fn from(value: SmallId) -> Self { Self(value.0 as u32) } } impl From for SmallId { fn from(value: Id) -> Self { Self(value.0 as u16) } }