use thiserror::Error;
use crate::{
EMLError, EMLValueResultExt as _, EMLVersion, EMLVersionRange, NS_EML, NS_KR,
io::{EMLElement, EMLElementReader, EMLElementWriter, QualifiedName},
utils::{StringValue, StringValueData},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GenderAnnex {
Male,
Female,
Other,
}
impl GenderAnnex {
pub fn new(s: impl AsRef<str>) -> Result<Self, EMLError> {
Self::from_eml_value(s).wrap_value_error()
}
pub fn from_eml_value(s: impl AsRef<str>) -> Result<Self, UnknownGenderError> {
let data = s.as_ref();
match data {
"male" => Ok(GenderAnnex::Male),
"female" => Ok(GenderAnnex::Female),
"other" => Ok(GenderAnnex::Other),
_ => Err(UnknownGenderError(data.to_string())),
}
}
pub fn to_eml_value(&self) -> &'static str {
match self {
GenderAnnex::Male => "male",
GenderAnnex::Female => "female",
GenderAnnex::Other => "other",
}
}
}
impl EMLElement for StringValue<GenderAnnex> {
const EML_NAME: QualifiedName<'_, '_> = QualifiedName::from_static("GenderAnnex", Some(NS_KR));
const EML_VERSIONS: EMLVersionRange = EMLVersionRange::since(EMLVersion::V1_3);
fn read_eml(elem: &mut EMLElementReader<'_, '_>) -> Result<Self, EMLError> {
elem.string_value()
}
fn write_eml(&self, writer: EMLElementWriter) -> Result<(), EMLError> {
writer.text(&self.raw())?.finish()
}
}
impl StringValueData for GenderAnnex {
type Error = UnknownGenderError;
fn parse_from_str(s: &str) -> Result<Self, Self::Error>
where
Self: Sized,
{
Self::from_eml_value(s)
}
fn to_raw_value(&self) -> Box<str> {
self.to_eml_value().into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Gender {
Male,
Female,
Unknown,
}
impl Gender {
pub fn new(s: impl AsRef<str>) -> Result<Self, EMLError> {
Self::from_eml_value(s).wrap_value_error()
}
pub fn from_eml_value(s: impl AsRef<str>) -> Result<Self, UnknownGenderError> {
let data = s.as_ref();
match data {
"male" => Ok(Gender::Male),
"female" => Ok(Gender::Female),
"unknown" => Ok(Gender::Unknown),
_ => Err(UnknownGenderError(data.to_string())),
}
}
pub fn to_eml_value(&self) -> &'static str {
match self {
Gender::Male => "male",
Gender::Female => "female",
Gender::Unknown => "unknown",
}
}
}
#[derive(Debug, Clone, Error, PartialEq, Eq)]
#[error("Unknown gender: {0}")]
pub struct UnknownGenderError(String);
impl From<UnknownGenderError> for EMLError {
fn from(err: UnknownGenderError) -> Self {
EMLError::value_conversion(err)
}
}
impl StringValueData for Gender {
type Error = UnknownGenderError;
fn parse_from_str(s: &str) -> Result<Self, Self::Error>
where
Self: Sized,
{
Self::from_eml_value(s)
}
fn to_raw_value(&self) -> Box<str> {
self.to_eml_value().into()
}
}
impl EMLElement for StringValue<Gender> {
const EML_NAME: QualifiedName<'static, 'static> =
QualifiedName::from_static("Gender", Some(NS_EML));
fn read_eml(elem: &mut EMLElementReader<'_, '_>) -> Result<Self, EMLError> {
elem.string_value::<Gender>()
}
fn write_eml(&self, writer: EMLElementWriter) -> Result<(), EMLError> {
writer.text(&self.raw())?.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid_gender_types() {
let valid_genders = ["male", "female", "unknown"];
for gender in valid_genders {
assert!(
Gender::from_eml_value(gender).is_ok(),
"Gender should accept valid gender: {}",
gender
);
}
}
#[test]
fn test_invalid_gender_types() {
let invalid_genders = ["", "test", "abc"];
for gender in invalid_genders {
assert!(
Gender::from_eml_value(gender).is_err(),
"Gender should reject invalid gender: {}",
gender
);
}
}
}