1use core::ffi::c_char;
2use core::ptr;
3use std::fmt;
4
5use serde::{Deserialize, Deserializer, Serialize};
6
7use crate::ffi;
8use crate::private::{error_from_status, string_from_ptr, to_cstring};
9use crate::translation_error::TranslationError;
10
11#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
12#[serde(transparent)]
13pub struct Language {
15 identifier: String,
16}
17
18impl<'de> Deserialize<'de> for Language {
19 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
20 where
21 D: Deserializer<'de>,
22 {
23 String::deserialize(deserializer).map(Self::new)
24 }
25}
26
27impl Language {
28 #[must_use]
29 pub fn new(identifier: impl Into<String>) -> Self {
31 Self {
32 identifier: identifier.into(),
33 }
34 }
35
36 #[must_use]
37 pub fn identifier(&self) -> &str {
39 &self.identifier
40 }
41
42 pub fn canonicalized(&self) -> Result<Self, TranslationError> {
44 let identifier = to_cstring(self.identifier())?;
45 let mut canonicalized: *mut c_char = ptr::null_mut();
46 let mut err_msg: *mut c_char = ptr::null_mut();
47 let status = unsafe {
48 ffi::trl_language_canonicalize(identifier.as_ptr(), &mut canonicalized, &mut err_msg)
49 };
50 if status == ffi::status::OK {
51 unsafe { string_from_ptr(canonicalized, "canonicalized language") }.map(Self::from)
52 } else {
53 Err(unsafe { error_from_status(status, err_msg) })
54 }
55 }
56}
57
58impl AsRef<str> for Language {
59 fn as_ref(&self) -> &str {
60 self.identifier()
61 }
62}
63
64impl From<&str> for Language {
65 fn from(identifier: &str) -> Self {
66 Self::new(identifier)
67 }
68}
69
70impl From<String> for Language {
71 fn from(identifier: String) -> Self {
72 Self::new(identifier)
73 }
74}
75
76impl From<Language> for String {
77 fn from(language: Language) -> Self {
78 language.identifier
79 }
80}
81
82impl fmt::Display for Language {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.write_str(self.identifier())
85 }
86}