use rusqlite::{types::{FromSql, FromSqlResult, ToSqlOutput, Value, ValueRef}, ToSql};
use std::{fmt::Display, hash::Hash};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default)]
pub struct AgentId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default)]
pub struct CrawlLogEntryId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct CrawlSummaryId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct EntityGenerationId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct FileInfoId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct MimetypeId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct OriginId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct RedirectId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct RequestId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct TokenId(i64);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct UrlId(i64);
pub trait NumericDatabseId: Eq + Clone + Copy + Hash {
fn new(id: i64) -> Self;
fn number(&self) -> i64;
}
impl NumericDatabseId for i64 {
fn new(id: i64) -> Self {
id
}
fn number(&self) -> i64 {
*self
}
}
macro_rules! impl_id {
($t:ty) => {
impl NumericDatabseId for $t {
#[inline]
fn new(id: i64) -> Self {
Self(id)
}
#[inline]
fn number(&self) -> i64 {
self.0
}
}
impl FromSql for $t {
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
Ok(Self(value.as_i64()?))
}
}
impl ToSql for $t {
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
}
}
impl Display for $t {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.0))
}
}
}
}
impl_id!(AgentId);
impl_id!(CrawlLogEntryId);
impl_id!(CrawlSummaryId);
impl_id!(EntityGenerationId);
impl_id!(FileInfoId);
impl_id!(MimetypeId);
impl_id!(OriginId);
impl_id!(RedirectId);
impl_id!(RequestId);
impl_id!(TokenId);
impl_id!(UrlId);