1#[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
22pub 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}