tina-core 0.0.2

Tina platform
Documentation
//! Id字段
use std::fmt::{Display, Formatter};

use crate::app_system_error;
use crate::tina::data::AppResult;
use serde_json::Value;

use super::app_error::AppError;

/// Id
#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
pub enum Id {
    /// 字符串
    String(String),
    /// 整型
    Number(i64),
}

impl Id {
    /// 从serde json的Value转换
    pub fn from_json_value(value: serde_json::Value) -> AppResult<Self> {
        match value {
            Value::Number(v) => match v.as_i64() {
                None => match v.as_u64() {
                    None => Err(crate::app_system_error!("can not parse {} to Id.", v)),
                    Some(v) => Ok(Id::Number(v as i64)),
                },
                Some(v) => Ok(Id::Number(v)),
            },
            Value::String(v) => Ok(Id::String(v)),
            _ => Err(crate::app_system_error!("can not parse {} to Id.", value)),
        }
    }
    /// 从rbatis的Value转换
    #[cfg(feature = "rbs")]
    pub fn from_rbatis_value(value: rbs::Value) -> AppResult<Self> {
        match value {
            rbs::Value::F32(v) => Ok(Id::from_i64(v as i64)),
            rbs::Value::F64(v) => Ok(Id::from_i64(v as i64)),
            rbs::Value::I32(v) => Ok(Id::from_i64(v as i64)),
            rbs::Value::I64(v) => Ok(Id::from_i64(v)),
            rbs::Value::U32(v) => Ok(Id::from_i64(v as i64)),
            rbs::Value::U64(v) => Ok(Id::from_i64(v as i64)),
            rbs::Value::String(v) => Ok(Id::from_string(v)),
            _ => Err(crate::app_system_error!("can not parse {} to Id.", value)),
        }
    }
    /// 从i64转换
    pub fn from_i64(value: i64) -> Self {
        Id::Number(value)
    }
    /// 从u64转换
    pub fn from_u64(value: u64) -> Self {
        Id::Number(value as i64)
    }
    /// 从String转换
    pub fn from_string(value: String) -> Self {
        Id::String(value)
    }
}

impl TryInto<i64> for Id {
    type Error = AppError;

    fn try_into(self) -> Result<i64, Self::Error> {
        match self {
            Id::String(v) => v.parse().map_err(|_| app_system_error!("can not parse Id to i64 with value {}", v)),
            Id::Number(v) => Ok(v),
        }
    }
}

impl TryInto<String> for Id {
    type Error = AppError;

    fn try_into(self) -> Result<String, Self::Error> {
        match self {
            Id::String(v) => Ok(v),
            Id::Number(v) => Ok(v.to_string()),
        }
    }
}

impl Default for Id {
    fn default() -> Self {
        Id::from_i64(0i64)
    }
}

impl Display for Id {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match &self {
            Id::String(v) => v.fmt(f),
            Id::Number(v) => v.fmt(f),
        }
    }
}

impl AsRef<Id> for Id {
    fn as_ref(&self) -> &Id {
        self
    }
}

/// 转换为Id
pub trait ToId {
    /// 转换为Id列表
    fn to_ids(&self) -> AppResult<Vec<Id>>;
    /// 转换为Id
    fn to_id(&self) -> AppResult<Id>;
}

impl<T> ToId for T
where
    T: AsRef<str>,
{
    fn to_ids(&self) -> AppResult<Vec<Id>> {
        let s = self.as_ref();
        let mut ids = Vec::new();
        for c in s.split(',') {
            let id = Id::from_i64(c.trim().parse().map_err(|err| app_system_error!("转换i64失败: {}, reason: {:?}", c, err))?);
            ids.push(id);
        }
        Ok(ids)
    }

    fn to_id(&self) -> AppResult<Id> {
        let s = self.as_ref();
        let id = Id::from_i64(s.trim().parse().map_err(|err| app_system_error!("转换i64失败: {}, reason: {:?}", s, err))?);
        Ok(id)
    }
}

mod ser {
    use crate::tina::data::id::Id;
    use serde::{Serialize, Serializer};

    impl Serialize for Id {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            #[cfg(feature = "bson")]
            {
                if std::any::type_name::<S>() == std::any::type_name::<bson::de::Deserializer>() {
                    return match &self {
                        Id::String(v) => {
                            let object_id = bson::oid::ObjectId::parse_str(v.as_str()).map_err(serde::ser::Error::custom)?;
                            object_id.serialize(serializer)
                        }
                        Id::Number(v) => v.serialize(serializer),
                    };
                }
            }
            match &self {
                Id::String(v) => serializer.serialize_str(v.as_str()),
                Id::Number(v) => serializer.serialize_i64(*v),
            }
        }
    }
}

mod de {
    use crate::tina::data::id::Id;
    use serde::de::{Error, Visitor};
    use serde::{Deserialize, Deserializer};
    use std::fmt::Formatter;

    struct IdVisitor;
    impl<'de> Visitor<'de> for IdVisitor {
        type Value = Id;

        fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
            formatter.write_str("Id must be integer value")
        }

        fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_i64(v as i64))
        }

        fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_i64(v as i64))
        }

        fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_i64(v as i64))
        }

        fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_i64(v))
        }

        fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_u64(v as u64))
        }

        fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_u64(v as u64))
        }

        fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_u64(v as u64))
        }

        fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
        where
            E: Error,
        {
            Ok(Id::from_u64(v))
        }

        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where
            E: Error,
        {
            let v = v.parse::<u64>().map_err(E::custom)?;
            Ok(Id::from_u64(v))
        }

        fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
        where
            E: Error,
        {
            let v = v.parse::<u64>().map_err(E::custom)?;
            Ok(Id::from_u64(v))
        }

        fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
        where
            E: Error,
        {
            let v = v.parse::<u64>().map_err(E::custom)?;
            Ok(Id::from_u64(v))
        }
    }

    impl<'de> Deserialize<'de> for Id {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            deserializer.deserialize_any(IdVisitor)
        }
    }
}