Skip to main content

locale_settings/
codeset.rs

1/*!
2Fetch locale-specific code-set settings.
3
4This module is relatively simple as only a small number of
5settings are defined by POSIX for the code-set category.
6
7*/
8
9use crate::ffi::utils::*;
10use crate::ffi::{___mb_cur_max, CODESET};
11use crate::Category;
12use locale_types::{Locale, LocaleResult};
13
14// ------------------------------------------------------------------------------------------------
15// Public Types
16// ------------------------------------------------------------------------------------------------
17
18/// Settings related to message display.
19#[derive(Debug, Clone, PartialEq)]
20pub struct CodeSetFormat {
21    /// The code set to use when displaying messages in the current locale.
22    /// Note that this does not return standard code set identifiers and so
23    /// this value cannot be used with the `codes::codesets` module.
24    pub code_set: Option<String>,
25    /// The maximum number of bytes needed to represent a single wide
26    /// character in the current locale.
27    pub multibyte_max_bytes: Option<u32>,
28}
29
30// ------------------------------------------------------------------------------------------------
31// Public Functions
32// ------------------------------------------------------------------------------------------------
33
34/// Fetch the code-set settings for the current locale.
35pub fn get_code_set_format() -> CodeSetFormat {
36    let mb_max_bytes = unsafe { ___mb_cur_max() as u32 };
37    CodeSetFormat {
38        code_set: get_nl_string(CODESET),
39        multibyte_max_bytes: Some(mb_max_bytes),
40    }
41}
42
43/// Fetch the code-set rules for a specified `Locale`.
44///
45/// # Arguments
46///
47/// * `locale` - The locale to query.
48/// * `inherit_current` - Whether the specified locale should inherit
49///   from the current locale.
50///
51/// If `inherit_current` is `false` the `locale` specified will be treated
52/// as an entirely new and complete locale when calling the C
53/// [`newlocale`](https://man.openbsd.org/newlocale.3) function. If it is
54/// `true` the `locale` is assumed to be a partially specified one and inherits
55/// any unspecified components from the current locale. For example, if the
56/// current locale is `en_US.UTF-8` and the parameters passed are `_NZ` and
57/// `true` then the resulting locale will be `en_NZ.UTF-8`.
58pub fn get_code_set_format_for_locale(
59    locale: Locale,
60    inherit_current: bool,
61) -> LocaleResult<CodeSetFormat> {
62    get_format_for_locale(
63        Category::CharacterTypes,
64        locale,
65        &get_code_set_format,
66        inherit_current,
67    )
68}
69
70// ------------------------------------------------------------------------------------------------
71// Unit Tests
72// ------------------------------------------------------------------------------------------------
73
74#[cfg(test)]
75mod tests {
76    use crate::codeset::{get_code_set_format, get_code_set_format_for_locale};
77    use crate::locale::{set_locale, Category};
78    use locale_types::Locale;
79    use std::str::FromStr;
80
81    // --------------------------------------------------------------------------------------------
82    #[test]
83    fn test_get_code_set_format() {
84        if set_locale(&Locale::POSIX, &Category::CharacterTypes) {
85            let format = get_code_set_format();
86            println!("{:#?}", format);
87            assert_eq!(format.code_set, Some("US-ASCII".to_string()));
88            assert_eq!(format.multibyte_max_bytes, Some(1));
89        } else {
90            panic!("set_locale returned false");
91        }
92    }
93
94    // --------------------------------------------------------------------------------------------
95    #[test]
96    fn test_get_code_set_format_for_locale() {
97        if set_locale(&Locale::POSIX, &Category::CharacterTypes) {
98            let format = get_code_set_format_for_locale(Locale::from_str("fr_FR").unwrap(), false);
99            println!("{:#?}", format);
100            let format = format.unwrap();
101            assert_eq!(format.code_set, None);
102            assert_eq!(format.multibyte_max_bytes, Some(4));
103        } else {
104            panic!("set_locale returned false");
105        }
106    }
107
108    #[test]
109    fn test_get_code_set_format_for_locale_2() {
110        if set_locale(&Locale::POSIX, &Category::CharacterTypes) {
111            let format =
112                get_code_set_format_for_locale(Locale::from_str("fr_FR.UTF-8").unwrap(), false);
113            println!("{:#?}", format);
114            let format = format.unwrap();
115            assert_eq!(format.code_set, Some("UTF-8".to_string()));
116            assert_eq!(format.multibyte_max_bytes, Some(4));
117        } else {
118            panic!("set_locale returned false");
119        }
120    }
121}