work
[pspp] / rust / src / encoding.rs
1 use encoding_rs::{Encoding, UTF_8};
2
3 include!(concat!(env!("OUT_DIR"), "/encodings.rs"));
4
5 pub fn codepage_from_encoding(encoding: &str) -> Option<u32> {
6     CODEPAGE_NAME_TO_NUMBER
7         .get(encoding.to_ascii_lowercase().as_str())
8         .copied()
9 }
10
11 use thiserror::Error as ThisError;
12
13 use crate::locale_charset::locale_charset;
14 #[derive(ThisError, Debug)]
15 pub enum Error {
16     #[error("This system file does not indicate its own character encoding.  For best results, specify an encoding explicitly.  Use SYSFILE INFO with ENCODING=\"DETECT\" to analyze the possible encodings.")]
17     NoEncoding,
18
19     #[error("This system file encodes text strings with unknown code page {0}.")]
20     UnknownCodepage(i32),
21
22     #[error("This system file is encoded in EBCDIC, which is not supported.")]
23     Ebcdic,
24 }
25
26
27 pub fn default_encoding() -> &'static Encoding {
28     lazy_static! {
29         static ref DEFAULT_ENCODING: &'static Encoding = {
30             Encoding::for_label(locale_charset()).unwrap_or(&UTF_8)
31         };
32     }
33     DEFAULT_ENCODING
34 }
35
36 pub fn get_encoding(encoding: Option<&str>, character_code: Option<i32>) -> Result<&str, Error> {
37     if let Some(encoding) = encoding {
38         Ok(encoding)
39     } else if let Some(codepage) = character_code {
40         match codepage {
41             1 => Err(Error::Ebcdic),
42             2 | 3 => {
43                 // These ostensibly mean "7-bit ASCII" and "8-bit ASCII"[sic]
44                 // respectively.  However, many files have character code 2 but
45                 // data which are clearly not ASCII.  Therefore, ignore these
46                 // values.
47                 Err(Error::NoEncoding)
48             }
49             4 => Ok("MS_KANJI"),
50             _ => CODEPAGE_NUMBER_TO_NAME
51                 .get(&codepage)
52                 .copied()
53                 .ok_or(Error::UnknownCodepage(codepage)),
54         }
55     } else {
56         Err(Error::NoEncoding)
57     }
58 }