use json_syntax::JsonString;
use langtag::{LangTag, LangTagBuf};
use crate::{JsonLdDirection, JsonLdLenient};
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct JsonLdLangString {
#[cfg_attr(feature = "serde", serde(rename = "@value"))]
data: JsonString,
#[cfg_attr(
feature = "serde",
serde(rename = "@language", skip_serializing_if = "Option::is_none")
)]
language: Option<JsonLdLenient<LangTagBuf>>,
#[cfg_attr(
feature = "serde",
serde(rename = "@direction", skip_serializing_if = "Option::is_none")
)]
direction: Option<JsonLdDirection>,
}
#[derive(Clone, Copy, Debug)]
pub struct InvalidJsonLdLangString;
impl JsonLdLangString {
pub fn new<T>(
data: T,
language: Option<JsonLdLenient<LangTagBuf>>,
direction: Option<JsonLdDirection>,
) -> Result<Self, T>
where
T: Into<JsonString>,
{
if language.is_some() || direction.is_some() {
Ok(Self {
data: data.into(),
language,
direction,
})
} else {
Err(data)
}
}
pub fn from_language(
data: impl Into<JsonString>,
language: impl Into<JsonLdLenient<LangTagBuf>>,
) -> Self {
Self {
data: data.into(),
language: Some(language.into()),
direction: None,
}
}
pub fn from_direction(data: impl Into<JsonString>, direction: JsonLdDirection) -> Self {
Self {
data: data.into(),
language: None,
direction: Some(direction),
}
}
pub fn into_parts(
self,
) -> (
JsonString,
Option<JsonLdLenient<LangTagBuf>>,
Option<JsonLdDirection>,
) {
(self.data, self.language, self.direction)
}
pub fn parts(
&self,
) -> (
&str,
Option<&JsonLdLenient<LangTagBuf>>,
Option<&JsonLdDirection>,
) {
(&self.data, self.language.as_ref(), self.direction.as_ref())
}
#[inline(always)]
pub fn as_str(&self) -> &str {
self.data.as_ref()
}
#[inline(always)]
pub fn language(&self) -> Option<JsonLdLenient<&LangTag>> {
self.language.as_ref().map(|tag| tag.as_deref())
}
pub fn set_language(
&mut self,
language: Option<JsonLdLenient<LangTagBuf>>,
) -> Result<(), InvalidJsonLdLangString> {
if self.direction.is_some() || language.is_some() {
self.language = language;
Ok(())
} else {
Err(InvalidJsonLdLangString)
}
}
#[inline(always)]
pub fn direction(&self) -> Option<JsonLdDirection> {
self.direction
}
pub fn set_direction(
&mut self,
direction: Option<JsonLdDirection>,
) -> Result<(), InvalidJsonLdLangString> {
if direction.is_some() || self.language.is_some() {
self.direction = direction;
Ok(())
} else {
Err(InvalidJsonLdLangString)
}
}
pub fn set(
&mut self,
language: Option<JsonLdLenient<LangTagBuf>>,
direction: Option<JsonLdDirection>,
) -> Result<(), InvalidJsonLdLangString> {
if direction.is_some() || language.is_some() {
self.language = language;
self.direction = direction;
Ok(())
} else {
Err(InvalidJsonLdLangString)
}
}
pub fn as_lang_str(&self) -> JsonLdLangStr<'_> {
JsonLdLangStr {
data: &self.data,
language: self.language.as_ref().map(JsonLdLenient::as_deref),
direction: self.direction,
}
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for JsonLdLangString {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(serde::Deserialize)]
struct Value {
#[serde(rename = "@value")]
data: JsonString,
#[serde(rename = "@language")]
language: Option<JsonLdLenient<LangTagBuf>>,
#[serde(rename = "@direction")]
direction: Option<JsonLdDirection>,
}
let value = Value::deserialize(deserializer)?;
Self::new(value.data, value.language, value.direction).map_err(serde::de::Error::custom)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct JsonLdLangStr<'a> {
#[cfg_attr(feature = "serde", serde(rename = "@value"))]
data: &'a str,
#[cfg_attr(
feature = "serde",
serde(rename = "@language", skip_serializing_if = "Option::is_none")
)]
language: Option<JsonLdLenient<&'a LangTag>>,
#[cfg_attr(
feature = "serde",
serde(rename = "@direction", skip_serializing_if = "Option::is_none")
)]
direction: Option<JsonLdDirection>,
}
impl<'a> JsonLdLangStr<'a> {
pub fn new(
data: &'a str,
language: Option<JsonLdLenient<&'a LangTag>>,
direction: Option<JsonLdDirection>,
) -> Result<Self, InvalidJsonLdLangString> {
if language.is_some() || direction.is_some() {
Ok(Self {
data,
language,
direction,
})
} else {
Err(InvalidJsonLdLangString)
}
}
pub fn into_parts(
self,
) -> (
&'a str,
Option<JsonLdLenient<&'a LangTag>>,
Option<JsonLdDirection>,
) {
(self.data, self.language, self.direction)
}
#[inline(always)]
pub fn as_str(&self) -> &'a str {
self.data
}
#[inline(always)]
pub fn language(&self) -> Option<JsonLdLenient<&'a LangTag>> {
self.language
}
#[inline(always)]
pub fn direction(&self) -> Option<JsonLdDirection> {
self.direction
}
}