[go: up one dir, main page]

sdl2/
locale.rs

1//! System locale information.
2
3/// A locale defines a user's language and (optionally) region.
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub struct Locale {
6    pub lang: String,
7    pub country: Option<String>,
8}
9
10impl std::fmt::Display for Locale {
11    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        write!(f, "{}", self.lang)?;
13
14        if let Some(region) = &self.country {
15            write!(f, "_{}", region)?;
16        }
17
18        Ok(())
19    }
20}
21
22/// Get the user's preferred locales.
23///
24/// [Official SDL documentation](https://wiki.libsdl.org/SDL_GetPreferredLocales)
25///
26/// # Example
27/// ```
28/// let locales = [sdl2::locale::Locale {
29///   lang: "en".to_string(),
30///   country: Some("US".to_string()),
31/// }];
32///
33/// sdl2::hint::set_preferred_locales(&locales);
34///
35/// let preferred_locales = sdl2::locale::get_preferred_locales().collect::<Vec<_>>();
36/// assert_eq!(preferred_locales, locales);
37/// ```
38pub fn get_preferred_locales() -> LocaleIterator {
39    unsafe {
40        LocaleIterator {
41            raw: sys::SDL_GetPreferredLocales(),
42            index: 0,
43        }
44    }
45}
46
47pub struct LocaleIterator {
48    raw: *mut sys::SDL_Locale,
49    index: isize,
50}
51
52impl Drop for LocaleIterator {
53    fn drop(&mut self) {
54        unsafe { sys::SDL_free(self.raw as *mut _) }
55    }
56}
57
58impl Iterator for LocaleIterator {
59    type Item = Locale;
60
61    fn next(&mut self) -> Option<Self::Item> {
62        let locale = unsafe { get_locale(self.raw.offset(self.index))? };
63        self.index += 1;
64        Some(locale)
65    }
66}
67
68unsafe fn get_locale(ptr: *const sys::SDL_Locale) -> Option<Locale> {
69    let sdl_locale = ptr.as_ref()?;
70
71    if sdl_locale.language.is_null() {
72        return None;
73    }
74    let lang = std::ffi::CStr::from_ptr(sdl_locale.language)
75        .to_string_lossy()
76        .into_owned();
77
78    let region = try_get_string(sdl_locale.country);
79
80    Some(Locale {
81        lang,
82        country: region,
83    })
84}
85
86unsafe fn try_get_string(ptr: *const libc::c_char) -> Option<String> {
87    if ptr.is_null() {
88        None
89    } else {
90        Some(std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned())
91    }
92}