// SPDX-License-Identifier: (0BSD or MIT) /* * advotracker - Hotline tackingtool for Advocats * * Copyright 2020-2021 Ralf Zerres */ // 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 ToSql for ConfirmState where DB: Backend, i32: ToSql, { fn to_sql(&self, out: &mut Output) -> 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); >::to_sql(&int_value, out) } } /* impl FromSql for ConfirmState { fn from_sql( bytes: Option<&::RawValue>, ) -> diesel::deserialize::Result { >::from_sql() .map(ConfirmState::Confirmed) } } */ impl FromSql for ConfirmState where DB: Backend, i32: FromSql, { fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result { match >::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 FromSql for ConfirmState where DB: Backend, i32: FromSql { //fn from_sql(bytes: Option::RawValue) -> diesel::deserialize::Result { fn from_sql( bytes: Option<&::RawValue>, ) -> diesel::deserialize::Result { //println!("Reading from sql: bytes:{:?}", bytes); match bytes { >::from_sql(bytes) .map(ConfirmState::Confirmed) } /* Some(bytes) => if bytes[0] != 0 { Ok(ConfirmState::Confirmed) } else { Ok(ConfirmState::Unconfirmed) } } //>::from_sql(bytes).map(ConfirmState::Confirmed) //fn from_sql(bytes: Option) -> diesel::deserialize::Result { // 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> diesel::deserialize::FromSql for ConfirmState { fn from_sql(bytes: Option<&[u8]>) -> diesel::deserialize::Result { >::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(self, value: bool) -> Result //where // E: de::Error, //{ // match value { // true => Ok(ConfirmState::Confirmed), // false => Ok(ConfirmState::Unconfirmed), // } //} fn visit_i32(self, value: &'a i32) -> Result where E: de::Error, { match >::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(self, value: &str) -> Result 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(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_any(ConfirmStateVisitor) } }