tina-core 0.0.2

Tina platform
Documentation
//! sort

use crate::tina::i18n::message::system_message::SystemMessage;
use crate::{app_param_check_error_with_msg, i18n_string};
use serde::de::{Error, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
    any::type_name,
    fmt::{Display, Formatter},
    str::FromStr,
};
use utoipa::{
    openapi::{schema::Schema, ObjectBuilder, RefOr, SchemaType},
    ToSchema,
};

use super::app_error::AppError;

/// 排序
#[derive(Debug, Copy, Clone)]
pub enum Sort {
    /// 升序
    Asc,
    /// 降序
    Desc,
}

impl FromStr for Sort {
    type Err = AppError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.trim().to_lowercase().as_str() {
            "ascending" | "ascend" | "asc" => Ok(Sort::Asc),
            "descending" | "descend" | "desc" => Ok(Sort::Desc),
            _ => Err(app_param_check_error_with_msg!(i18n_string!(
                SystemMessage::ERROR_SORT_VALUE_MUST_BE_IN_THESE,
                ("name", "[ascending,asc,descending,desc]")
            ))),
        }
    }
}

impl Display for Sort {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            Sort::Asc => "asc",
            Sort::Desc => "desc",
        };
        f.write_str(s)
    }
}

impl Default for Sort {
    fn default() -> Self {
        Self::Desc
    }
}

impl<'a> ToSchema<'a> for Sort {
    fn schema() -> (&'a str, RefOr<Schema>) {
        (
            type_name::<Sort>(),
            RefOr::T(Schema::from(
                ObjectBuilder::new()
                    .schema_type(SchemaType::String)
                    .description(Some("排序"))
                    .enum_values(Some(vec!["ascending", "descending", "asc", "desc"])),
            )),
        )
    }
}

impl Serialize for Sort {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Sort::Asc => serializer.serialize_str("asc"),
            Sort::Desc => serializer.serialize_str("desc"),
        }
    }
}

struct SortVisitor;

impl<'de> Visitor<'de> for SortVisitor {
    type Value = Sort;

    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_str("ascending, descending, asc or desc")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Sort::from_str(v).map_err(E::custom)
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Sort::from_str(v).map_err(E::custom)
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Sort::from_str(v.as_str()).map_err(E::custom)
    }
}

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