open_timeline_core/
name.rs1use serde::{Deserialize, Deserializer, Serialize};
8use thiserror::Error;
9
10#[derive(Error, Debug, Clone)]
13pub enum NameError {
14 #[error("Name cannot be empty")]
15 Empty,
16}
17
18#[derive(derive_more::Display, Serialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
23#[cfg_attr(feature = "sqlx", sqlx(transparent))]
24pub struct Name(String);
25
26impl Name {
27 pub fn from<S: ToString>(name: S) -> Result<Self, NameError> {
29 let name = name.to_string();
30 if name.trim().is_empty() {
31 Err(NameError::Empty)
32 } else {
33 Ok(Name(name.trim().to_string()))
34 }
35 }
36
37 pub fn as_str(&self) -> &str {
39 &self.0
40 }
41}
42
43impl<'de> Deserialize<'de> for Name {
44 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45 where
46 D: Deserializer<'de>,
47 {
48 let string = String::deserialize(deserializer)?;
49 Name::from(string).map_err(serde::de::Error::custom)
50 }
51}
52
53#[cfg(test)]
54mod test {
55 use super::*;
56
57 #[test]
58 fn from() {
59 assert!(Name::from("").is_err());
60 assert!(Name::from(" ").is_err());
61 let ok_1 = Name::from("Pass").unwrap();
62 let ok_2 = Name::from(" Pass ").unwrap();
63 assert_eq!(ok_1, ok_2)
64 }
65}