introduce traits for the user model
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
This commit is contained in:
192
src/models/users/trait.rs
Normal file
192
src/models/users/trait.rs
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* advotracker - Hotline tackingtool for Advocats
|
||||
*
|
||||
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
|
||||
* SPDX-License-Identifier: (0BSD or MIT)
|
||||
*/
|
||||
|
||||
// bring models into scope
|
||||
use diesel::backend::Backend;
|
||||
use diesel::deserialize;
|
||||
use diesel::deserialize::FromSql;
|
||||
use diesel::serialize;
|
||||
use diesel::serialize::{Output, ToSql};
|
||||
use diesel::sql_types::Integer;
|
||||
//use serde::Serializer;
|
||||
use serde;
|
||||
|
||||
//use super::models::ConfirmState;
|
||||
//use crate::db::models::ConfirmState;
|
||||
|
||||
// trait: meaningful enum/types for email confirmation states
|
||||
// in analogy: https://noyez.gitlab.io/post/2018-08-05-a-small-custom-bool-type-in-diesel/
|
||||
|
||||
//#[repr(i32)]
|
||||
#[derive(AsExpression, Copy, Clone, Debug, PartialEq, FromSqlRow)]
|
||||
#[sql_type = "Integer"]
|
||||
pub enum ConfirmState {
|
||||
Unconfirmed = 0,
|
||||
Confirmed = 1,
|
||||
Authorized = 2,
|
||||
Blocked = 3,
|
||||
}
|
||||
|
||||
impl<DB> ToSql<Integer, DB> for ConfirmState
|
||||
where
|
||||
DB: Backend,
|
||||
i32: ToSql<Integer, DB>,
|
||||
{
|
||||
fn to_sql<W: std::io::Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
|
||||
let int_value;
|
||||
match &self {
|
||||
ConfirmState::Unconfirmed => int_value = 0,
|
||||
ConfirmState::Confirmed => int_value = 1,
|
||||
ConfirmState::Authorized => int_value = 2,
|
||||
ConfirmState::Blocked => int_value = 3,
|
||||
}
|
||||
println!("Writing to sql: i32:{:?}", &int_value);
|
||||
<i32 as ToSql<Integer, DB>>::to_sql(&int_value, out)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl FromSql<Integer, Sqlite>
|
||||
for ConfirmState
|
||||
{
|
||||
fn from_sql(
|
||||
bytes: Option<&<diesel::sqlite::Sqlite as diesel::backend::Backend>::RawValue>,
|
||||
) -> diesel::deserialize::Result<Self> {
|
||||
<i32 as diesel::deserialize::FromSql<
|
||||
diesel::sql_types::Integer, diesel::sqlite::Sqlite>>::from_sql()
|
||||
.map(ConfirmState::Confirmed)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl<DB> FromSql<Integer, DB> for ConfirmState
|
||||
where
|
||||
DB: Backend<RawValue = [u8]>,
|
||||
i32: FromSql<Integer, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
match <i32 as FromSql<Integer, DB>>::from_sql(bytes)? {
|
||||
0 => Ok(ConfirmState::Unconfirmed),
|
||||
1 => Ok(ConfirmState::Confirmed),
|
||||
2 => Ok(ConfirmState::Authorized),
|
||||
3 => Ok(ConfirmState::Blocked),
|
||||
x => Err(format!("Unrecognized variant {}", x).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// WIP
|
||||
|
||||
impl<DB> FromSql<Integer, DB> for ConfirmState
|
||||
where
|
||||
DB: Backend,
|
||||
i32: FromSql<Bool, DB> {
|
||||
//fn from_sql(bytes: Option<diesel::backend::Backend>::RawValue<DB>) -> diesel::deserialize::Result<Self> {
|
||||
fn from_sql(
|
||||
bytes: Option<&<DB>::RawValue>,
|
||||
) -> diesel::deserialize::Result<Self> {
|
||||
//println!("Reading from sql: bytes:{:?}", bytes);
|
||||
match bytes {
|
||||
<i32 as diesel::deserialize::FromSql<Integer, DB>>::from_sql(bytes)
|
||||
.map(ConfirmState::Confirmed)
|
||||
}
|
||||
/*
|
||||
Some(bytes) => if bytes[0] != 0 {
|
||||
Ok(ConfirmState::Confirmed) }
|
||||
else { Ok(ConfirmState::Unconfirmed) }
|
||||
}
|
||||
//<i32 as diesel::deserialize::FromSql<Integer, DB>>::from_sql(bytes).map(ConfirmState::Confirmed)
|
||||
//fn from_sql(bytes: Option<Bool>) -> diesel::deserialize::Result<Self> {
|
||||
// println!("Reading from sql: bytes:{:?}", bytes);
|
||||
// match bytes {
|
||||
// Some(bytes) => if bytes[0] != 0 {
|
||||
// Ok(ConfirmState::Confirmed) }
|
||||
// else { Ok(ConfirmState::Unconfirmed) },
|
||||
// None => Ok(ConfirmState::Unconfirmed),
|
||||
// }
|
||||
*/
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
impl<DB: diesel::backend::Backend<RawValue = [u8]>>
|
||||
diesel::deserialize::FromSql<diesel::sql_types::Integer, DB> for ConfirmState
|
||||
{
|
||||
fn from_sql(bytes: Option<&[u8]>) -> diesel::deserialize::Result<Self> {
|
||||
<i32 as diesel::deserialize::FromSql<diesel::sql_types::Integer, DB>>::from_sql(
|
||||
bytes,
|
||||
)
|
||||
.map($name)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
struct ConfirmStateVisitor;
|
||||
use serde::de::Deserialize;
|
||||
use serde::de::{self, Visitor};
|
||||
|
||||
impl<'de> Visitor<'de> for ConfirmStateVisitor {
|
||||
type Value = ConfirmState;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("an integer or string of ",
|
||||
"\"Unconfirmed (0)\",",
|
||||
"\"Confirmed (1)\"",
|
||||
"\"Authorized (2)\"",
|
||||
"\"Blocked (3)\".");
|
||||
}
|
||||
|
||||
//fn visit_bool<E>(self, value: bool) -> Result<ConfirmState, E>
|
||||
//where
|
||||
// E: de::Error,
|
||||
//{
|
||||
// match value {
|
||||
// true => Ok(ConfirmState::Confirmed),
|
||||
// false => Ok(ConfirmState::Unconfirmed),
|
||||
// }
|
||||
//}
|
||||
|
||||
fn visit_i32<E>(self, value: &'a i32) -> Result<self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match <i32 as FromSql<Integer, DB>>::from_sql(bytes)? {
|
||||
0 => Ok(ConfirmState::Unconfirmed),
|
||||
1 => Ok(ConfirmState::Confirmed),
|
||||
2 => Ok(ConfirmState::Authorized),
|
||||
3 => Ok(ConfirmState::Blocked),
|
||||
x => Err(format!("Unrecognized variant {}", x).into()),
|
||||
0 => Ok(ConfirmState::Confirmed),
|
||||
false => Ok(ConfirmState::Unconfirmed),
|
||||
}
|
||||
}
|
||||
fn visit_str<E>(self, value: &str) -> Result<self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
//"Confirmed" | "Authorized" => Ok(ConfirmState::Confirmed),
|
||||
//"Unconfirmed" | "Unauthorized" => Ok(ConfirmState::Unconfirmed),
|
||||
"Unconfirmed" => Ok(ConfirmState::Unconfirmed),
|
||||
"Confirmed" => Ok(ConfirmState::Confirmed),
|
||||
"Authorized" => Ok(ConfirmState::Authorized),
|
||||
"Bolcked" => Ok(ConfirmState::Blocked),
|
||||
_s => Err(E::custom(format!("Unknown string value: {}", _s))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ConfirmState {
|
||||
fn deserialize<D>(deserializer: D) -> Result<self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(ConfirmStateVisitor)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user