use std::fmt;
use std::hash::Hash;
use derive_more::{AsRef, From, Into};
use mti::prelude::*;
use crate::errors::ErnError;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(AsRef, From, Into, Eq, Debug, PartialEq, Clone, Hash, Default, PartialOrd)]
pub struct EntityRoot {
name: MagicTypeId,
}
impl EntityRoot {
pub fn name(&self) -> &MagicTypeId {
&self.name
}
pub fn as_str(&self) -> &str {
&self.name
}
pub fn new(value: String) -> Result<Self, ErnError> {
if value.is_empty() {
return Err(ErnError::ParseFailure(
"EntityRoot",
"cannot be empty".to_string(),
));
}
if value.len() > 255 {
return Err(ErnError::ParseFailure(
"EntityRoot",
format!(
"length exceeds maximum of 255 characters (got {})",
value.len()
),
));
}
Ok(EntityRoot {
name: value.create_type_id::<V7>(),
})
}
}
impl fmt::Display for EntityRoot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let id = &self.name;
write!(f, "{id}")
}
}
impl std::str::FromStr for EntityRoot {
type Err = ErnError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() {
return Err(ErnError::ParseFailure(
"EntityRoot",
"cannot be empty".to_string(),
));
}
if s.len() > 255 {
return Err(ErnError::ParseFailure(
"EntityRoot",
format!("length exceeds maximum of 255 characters (got {})", s.len()),
));
}
Ok(EntityRoot {
name: s.create_type_id::<V7>(),
})
}
}
#[cfg(feature = "serde")]
impl Serialize for EntityRoot {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.name.as_ref())
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for EntityRoot {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
EntityRoot::new(s).map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn test_entity_root_creation() -> anyhow::Result<()> {
let root = EntityRoot::new("test-entity".to_string())?;
assert!(!root.to_string().is_empty());
Ok(())
}
#[test]
fn test_entity_root_uniqueness() -> anyhow::Result<()> {
let root1 = EntityRoot::new("same-content".to_string())?;
let root2 = EntityRoot::new("same-content".to_string())?;
assert_ne!(root1.to_string(), root2.to_string());
Ok(())
}
#[test]
fn test_entity_root_from_str() -> anyhow::Result<()> {
let root = EntityRoot::from_str("test-entity")?;
assert!(!root.to_string().is_empty());
Ok(())
}
#[test]
fn test_entity_root_validation_empty() {
let result = EntityRoot::new("".to_string());
assert!(result.is_err());
match result {
Err(ErnError::ParseFailure(component, msg)) => {
assert_eq!(component, "EntityRoot");
assert!(msg.contains("empty"));
}
_ => panic!("Expected ParseFailure error for empty EntityRoot"),
}
}
#[test]
fn test_entity_root_validation_too_long() {
let long_value = "a".repeat(256);
let result = EntityRoot::new(long_value);
assert!(result.is_err());
match result {
Err(ErnError::ParseFailure(component, msg)) => {
assert_eq!(component, "EntityRoot");
assert!(msg.contains("length exceeds maximum"));
}
_ => panic!("Expected ParseFailure error for too long EntityRoot"),
}
}
#[test]
fn test_entity_root_from_str_validation() {
let result = EntityRoot::from_str("");
assert!(result.is_err());
match result {
Err(ErnError::ParseFailure(component, msg)) => {
assert_eq!(component, "EntityRoot");
assert!(msg.contains("empty"));
}
_ => panic!("Expected ParseFailure error for empty EntityRoot from_str"),
}
}
}