use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum ColumnFlag {
Id,
Title,
Searchable,
Orderable,
Mandatory,
Hidden,
RequestParam,
Calculated,
Auto,
Other(String),
}
impl ColumnFlag {
pub fn as_str(&self) -> &str {
match self {
ColumnFlag::Id => "id",
ColumnFlag::Title => "title",
ColumnFlag::Searchable => "searchable",
ColumnFlag::Orderable => "orderable",
ColumnFlag::Mandatory => "mandatory",
ColumnFlag::Hidden => "hidden",
ColumnFlag::RequestParam => "request_param",
ColumnFlag::Calculated => "calculated",
ColumnFlag::Auto => "auto",
ColumnFlag::Other(name) => name,
}
}
}
impl PartialEq for ColumnFlag {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl Eq for ColumnFlag {}
impl std::hash::Hash for ColumnFlag {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state)
}
}
impl From<&str> for ColumnFlag {
fn from(name: &str) -> Self {
match name {
"id" => ColumnFlag::Id,
"title" => ColumnFlag::Title,
"searchable" => ColumnFlag::Searchable,
"orderable" => ColumnFlag::Orderable,
"mandatory" => ColumnFlag::Mandatory,
"hidden" => ColumnFlag::Hidden,
"request_param" => ColumnFlag::RequestParam,
"calculated" => ColumnFlag::Calculated,
"auto" => ColumnFlag::Auto,
other => ColumnFlag::Other(other.to_string()),
}
}
}
impl From<String> for ColumnFlag {
fn from(name: String) -> Self {
ColumnFlag::from(name.as_str())
}
}
impl fmt::Display for ColumnFlag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl Serialize for ColumnFlag {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for ColumnFlag {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(ColumnFlag::from(String::deserialize(deserializer)?))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn yaml_names_map_onto_variants() {
let flags: Vec<ColumnFlag> =
serde_yaml_ng::from_str("[id, searchable, request_param, label]").unwrap();
assert_eq!(
flags,
[
ColumnFlag::Id,
ColumnFlag::Searchable,
ColumnFlag::RequestParam,
ColumnFlag::Other("label".into())
]
);
assert!(matches!(flags[2], ColumnFlag::RequestParam));
assert_eq!(
serde_yaml_ng::to_string(&flags).unwrap(),
"- id\n- searchable\n- request_param\n- label\n"
);
}
#[test]
fn a_hand_built_other_with_a_known_name_is_that_flag() {
assert_eq!(ColumnFlag::Other("id".into()), ColumnFlag::Id);
let column = crate::Column::new("a", "int").with_flag(ColumnFlag::Other("hidden".into()));
assert!(column.has_flag(ColumnFlag::Hidden));
assert!(matches!(ColumnFlag::from("hidden"), ColumnFlag::Hidden));
}
}