Skip to main content

translation/
language.rs

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)]
13/// Wraps a Translation.framework language identifier.
14pub 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    /// Creates a language wrapper from a BCP-47 identifier.
30    pub fn new(identifier: impl Into<String>) -> Self {
31        Self {
32            identifier: identifier.into(),
33        }
34    }
35
36    #[must_use]
37    /// Returns the wrapped language identifier.
38    pub fn identifier(&self) -> &str {
39        &self.identifier
40    }
41
42    /// Returns the Translation.framework-canonicalized language identifier.
43    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}