use crate::utilities::{
deserialize_normalized_lang_tag, deserialize_normalized_text, validate_text,
};
use oxilangtag::{LanguageTag, LanguageTagParseError};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use thiserror::Error;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct LangString {
#[serde(deserialize_with = "deserialize_normalized_lang_tag")]
pub language: LanguageTag<String>,
#[serde(deserialize_with = "deserialize_normalized_text")]
pub text: String,
}
impl Default for LangString {
fn default() -> Self {
Self {
language: LanguageTag::parse_and_normalize("en").unwrap(),
text: String::default(),
}
}
}
#[derive(Error, Debug)]
pub enum LangStringParseRDFError {
#[error("The format of the RDF/Turtle syntax is wrong and cannot be parsed")]
IncorrectFormat,
#[error("The Text part does contain non valid characters specified by the AAS spec")]
NonValidCharacters,
#[error("Language tag couldn't be parsed")]
ParseError(#[from] LanguageTagParseError),
}
impl LangString {
pub fn try_new(language: &str, text: String) -> Result<Self, LanguageTagParseError> {
let language = LanguageTag::parse_and_normalize(language)?;
Ok(Self { language, text })
}
}
impl FromStr for LangString {
type Err = LangStringParseRDFError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let lang_string: Vec<&str> = s.split('@').collect();
if lang_string.len() != 2 {
return Err(LangStringParseRDFError::IncorrectFormat);
}
let mut text = String::from(lang_string[0]);
if text.len() < 2 {
return Err(LangStringParseRDFError::IncorrectFormat);
}
let (q1, q2) = (text.remove(0), text.remove(text.len() - 1));
if q1 != '\"' || q2 != '\"' {
return Err(LangStringParseRDFError::IncorrectFormat);
}
if !validate_text(&text) {
return Err(LangStringParseRDFError::NonValidCharacters);
}
let language = LanguageTag::parse_and_normalize(lang_string[1])
.map_err(LangStringParseRDFError::ParseError)?;
Ok(LangString { language, text })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_turtle_syntax() {
let expected = LangString::try_new("EN", "Sample text".to_string()).unwrap();
let turtle_parsed = LangString::from_str(r#""Sample text"@EN"#).ok().unwrap();
assert_eq!(turtle_parsed, expected);
}
#[test]
fn turtle_syntax_empty_text() {
let expected = LangString::try_new("EN", "".to_string()).unwrap();
let turtle_parsed = LangString::from_str(r#"""@EN"#).ok().unwrap();
assert_eq!(turtle_parsed, expected);
}
#[test]
#[should_panic]
fn turtle_syntax_no_text_no_quotes() {
LangString::from_str(r#"@EN"#).unwrap();
}
#[test]
fn test_deserialize() {
let json = r#"
{
"language": "EN",
"text": "Sample test text"
}"#;
let expected = LangString::try_new("EN", "Sample test text".to_string()).unwrap();
let deserialized = serde_json::from_str(json).expect("Should deserialize");
assert_eq!(expected, deserialized);
}
}