//! What a feature refers to: bodies and features by name, sketches by id. Each is saved as the //! plain name or id it wraps, but has its own type, so a body name can't be passed where a //! feature name or an expression is meant. use std::ops::Deref; use serde::{Deserialize, Serialize}; macro_rules! name_type { ($(#[$doc:meta])* $name:ident) => { $(#[$doc])* #[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] #[serde(transparent)] pub struct $name(pub String); impl Deref for $name { type Target = str; fn deref(&self) -> &str { &self.0 } } impl AsRef for $name { fn as_ref(&self) -> &str { &self.0 } } impl std::borrow::Borrow for $name { fn borrow(&self) -> &str { &self.0 } } impl From for $name { fn from(s: String) -> Self { $name(s) } } impl From<&str> for $name { fn from(s: &str) -> Self { $name(s.to_string()) } } impl From<&String> for $name { fn from(s: &String) -> Self { $name(s.clone()) } } impl From<$name> for String { fn from(n: $name) -> String { n.0 } } impl std::fmt::Display for $name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0) } } impl PartialEq for $name { fn eq(&self, other: &str) -> bool { self.0 == other } } impl PartialEq<&str> for $name { fn eq(&self, other: &&str) -> bool { self.0 == *other } } impl PartialEq for $name { fn eq(&self, other: &String) -> bool { &self.0 == other } } impl PartialEq<$name> for String { fn eq(&self, other: &$name) -> bool { *self == other.0 } } impl PartialEq<$name> for str { fn eq(&self, other: &$name) -> bool { self == other.0 } } }; } name_type!( /// A body, by name. BodyName ); name_type!( /// A feature, by name. FeatureName ); /// A sketch, by its feature id. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] #[serde(transparent)] pub struct SketchId(pub u64); impl Deref for SketchId { type Target = u64; fn deref(&self) -> &u64 { &self.0 } } impl From for SketchId { fn from(id: u64) -> Self { SketchId(id) } } impl From for u64 { fn from(id: SketchId) -> u64 { id.0 } } impl PartialEq for SketchId { fn eq(&self, other: &u64) -> bool { self.0 == *other } } impl PartialEq for u64 { fn eq(&self, other: &SketchId) -> bool { *self == other.0 } } impl std::fmt::Display for SketchId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) } }