use std::fmt::Debug;
#[derive(Debug, Clone)]
pub enum UnstructuredText<LC: AllowedLanguages = AnyLanguage> {
Url(String),
Text {
text: String,
language_code: Option<LC>,
},
}
impl<T: AllowedLanguages> UnstructuredText<T> {
pub fn from_inline(text: impl Into<String>, language_code: T) -> UnstructuredText<T> {
UnstructuredText::Text {
text: text.into(),
language_code: Some(language_code),
}
}
#[cfg(any(feature = "host", feature = "guest"))]
pub fn from_wit_value(value: crate::WitValue) -> Result<UnstructuredText<T>, String> {
let value = crate::Value::from(value);
match value {
crate::Value::Variant {
case_value,
case_idx,
} => match case_idx {
0 => {
if let Some(boxed_url) = case_value {
if let crate::Value::String(url) = *boxed_url {
Ok(UnstructuredText::Url(url))
} else {
Err("Expected String for URL variant".to_string())
}
} else {
Err("Expected value for URL variant".to_string())
}
}
1 => {
if let Some(boxed_record) = case_value {
if let crate::Value::Record(mut fields) = *boxed_record {
if fields.len() != 2 {
return Err("Expected 2 fields in Inline variant".to_string());
}
let text_value = fields.remove(0);
let lang_option_value = fields.remove(0);
let text = if let crate::Value::String(t) = text_value {
t
} else {
return Err("Expected String for text field".to_string());
};
let language_code = match lang_option_value {
crate::Value::Option(Some(boxed_lang_record)) => {
if let crate::Value::Record(lang_fields) = *boxed_lang_record {
if lang_fields.len() != 1 {
return Err("Expected 1 field in language code record"
.to_string());
}
if let crate::Value::String(code) = &lang_fields[0] {
T::from_language_code(code)
} else {
return Err(
"Expected String for language code".to_string()
);
}
} else {
return Err("Expected Record for language code".to_string());
}
}
_ => None,
};
Ok(UnstructuredText::Text {
text,
language_code,
})
} else {
Err("Expected Record for Inline variant".to_string())
}
} else {
Err("Expected value for Inline variant".to_string())
}
}
_ => Err("Unknown variant index for UnstructuredText".to_string()),
},
_ => Err("Expected Variant value for UnstructuredText".to_string()),
}
}
}
impl UnstructuredText<AnyLanguage> {
pub fn from_url_any(url: impl Into<String>) -> UnstructuredText<AnyLanguage> {
UnstructuredText::Url(url.into())
}
pub fn from_inline_any(text: impl Into<String>) -> UnstructuredText<AnyLanguage> {
UnstructuredText::Text {
text: text.into(),
language_code: None,
}
}
}
pub trait AllowedLanguages: Debug + Clone {
fn all() -> &'static [&'static str];
fn from_language_code(code: &str) -> Option<Self>
where
Self: Sized;
fn to_language_code(&self) -> &'static str;
}
#[derive(Debug, Clone)]
pub struct AnyLanguage;
impl AllowedLanguages for AnyLanguage {
fn all() -> &'static [&'static str] {
&[]
}
fn from_language_code(_code: &str) -> Option<Self> {
None
}
fn to_language_code(&self) -> &'static str {
""
}
}