simple_fatfs/
codepage.rs

1#[cfg(not(feature = "std"))]
2use alloc::{boxed::Box, string::String};
3
4#[derive(Debug, Clone, Copy)]
5/// Windows codepage to use for encoding/decoding short filenames
6///
7/// Windows codepages are an extension of ASCII. They were in use by
8/// Microsoft all the way back in the '80s and '90s. FAT uses them
9/// only for the short file names and they don't play much of a big role
10/// in it. They are used by this library for maximal backwards compatibility.
11/// Virtually all FAT implementations use the 437 OEM codepage (OEM United States),
12/// which is the default codepage.
13pub enum Codepage {
14    /// OEM United States
15    CP437,
16    /// Arabic (Transparent ASMO); Arabic (DOS)
17    CP720,
18    /// OEM Greek (formerly 437G); Greek (DOS)
19    CP737,
20    /// OEM Baltic; Baltic (DOS)
21    CP775,
22    /// OEM Multilingual Latin 1; Western European (DOS)
23    CP850,
24    /// OEM Latin 2; Central European (DOS)
25    CP852,
26    /// OEM Cyrillic (primarily Russian)
27    CP855,
28    /// OEM Turkish; Turkish (DOS)
29    CP857,
30    /// OEM Multilingual Latin 1 + Euro symbol
31    CP858,
32    /// OEM Portuguese; Portuguese (DOS)
33    CP860,
34    /// OEM Icelandic; Icelandic (DOS)
35    CP861,
36    /// OEM Hebrew; Hebrew (DOS)
37    CP862,
38    /// OEM French Canadian; French Canadian (DOS)
39    CP863,
40    /// OEM Arabic; Arabic (864)
41    CP864,
42    /// OEM Nordic; Nordic (DOS)
43    CP865,
44    /// OEM Russian; Cyrillic (DOS)
45    CP866,
46    /// OEM Modern Greek; Greek, Modern (DOS)
47    CP869,
48    /// ANSI/OEM Thai (ISO 8859-11); Thai (Windows)
49    CP874,
50}
51
52impl Codepage {
53    pub(crate) fn decode(&self, v: &[u8]) -> String {
54        use oem_cp::{decode_string_complete_table, decode_string_incomplete_table_lossy};
55
56        match self {
57            Codepage::CP437 => {
58                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP437)
59            }
60            Codepage::CP720 => {
61                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP720)
62            }
63            Codepage::CP737 => {
64                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP737)
65            }
66            Codepage::CP775 => {
67                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP775)
68            }
69            Codepage::CP850 => {
70                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP850)
71            }
72            Codepage::CP852 => {
73                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP852)
74            }
75            Codepage::CP855 => {
76                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP855)
77            }
78            Codepage::CP857 => {
79                decode_string_incomplete_table_lossy(v, &oem_cp::code_table::DECODING_TABLE_CP857)
80            }
81            Codepage::CP858 => {
82                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP858)
83            }
84            Codepage::CP860 => {
85                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP860)
86            }
87            Codepage::CP861 => {
88                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP861)
89            }
90            Codepage::CP862 => {
91                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP862)
92            }
93            Codepage::CP863 => {
94                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP863)
95            }
96            Codepage::CP864 => {
97                decode_string_incomplete_table_lossy(v, &oem_cp::code_table::DECODING_TABLE_CP864)
98            }
99            Codepage::CP865 => {
100                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP865)
101            }
102            Codepage::CP866 => {
103                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP866)
104            }
105            Codepage::CP869 => {
106                decode_string_complete_table(v, &oem_cp::code_table::DECODING_TABLE_CP869)
107            }
108            Codepage::CP874 => {
109                decode_string_incomplete_table_lossy(v, &oem_cp::code_table::DECODING_TABLE_CP874)
110            }
111        }
112    }
113
114    // this might come in handy in the future
115    #[allow(unused)]
116    pub(crate) fn encode(&self, s: &str) -> Box<[u8]> {
117        use oem_cp::encode_string_lossy;
118
119        match self {
120            Codepage::CP437 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP437),
121            Codepage::CP720 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP720),
122            Codepage::CP737 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP737),
123            Codepage::CP775 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP775),
124            Codepage::CP850 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP850),
125            Codepage::CP852 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP852),
126            Codepage::CP855 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP855),
127            Codepage::CP857 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP857),
128            Codepage::CP858 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP858),
129            Codepage::CP860 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP860),
130            Codepage::CP861 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP861),
131            Codepage::CP862 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP862),
132            Codepage::CP863 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP863),
133            Codepage::CP864 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP864),
134            Codepage::CP865 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP865),
135            Codepage::CP866 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP866),
136            Codepage::CP869 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP869),
137            Codepage::CP874 => encode_string_lossy(s, &oem_cp::code_table::ENCODING_TABLE_CP874),
138        }
139        .into_boxed_slice()
140    }
141
142    pub(crate) fn contains(&self, c: char) -> bool {
143        if c.is_ascii() {
144            return true;
145        }
146
147        match self {
148            Codepage::CP437 => oem_cp::code_table::DECODING_TABLE_CP437.contains(&c),
149            Codepage::CP720 => oem_cp::code_table::DECODING_TABLE_CP720.contains(&c),
150            Codepage::CP737 => oem_cp::code_table::DECODING_TABLE_CP737.contains(&c),
151            Codepage::CP775 => oem_cp::code_table::DECODING_TABLE_CP775.contains(&c),
152            Codepage::CP850 => oem_cp::code_table::DECODING_TABLE_CP850.contains(&c),
153            Codepage::CP852 => oem_cp::code_table::DECODING_TABLE_CP852.contains(&c),
154            Codepage::CP855 => oem_cp::code_table::DECODING_TABLE_CP855.contains(&c),
155            Codepage::CP857 => oem_cp::code_table::DECODING_TABLE_CP857.contains(&Some(c)),
156            Codepage::CP858 => oem_cp::code_table::DECODING_TABLE_CP858.contains(&c),
157            Codepage::CP860 => oem_cp::code_table::DECODING_TABLE_CP860.contains(&c),
158            Codepage::CP861 => oem_cp::code_table::DECODING_TABLE_CP861.contains(&c),
159            Codepage::CP862 => oem_cp::code_table::DECODING_TABLE_CP862.contains(&c),
160            Codepage::CP863 => oem_cp::code_table::DECODING_TABLE_CP863.contains(&c),
161            Codepage::CP864 => oem_cp::code_table::DECODING_TABLE_CP864.contains(&Some(c)),
162            Codepage::CP865 => oem_cp::code_table::DECODING_TABLE_CP865.contains(&c),
163            Codepage::CP866 => oem_cp::code_table::DECODING_TABLE_CP866.contains(&c),
164            Codepage::CP869 => oem_cp::code_table::DECODING_TABLE_CP869.contains(&c),
165            Codepage::CP874 => oem_cp::code_table::DECODING_TABLE_CP874.contains(&Some(c)),
166        }
167    }
168}
169
170impl TryFrom<u16> for Codepage {
171    type Error = ();
172
173    fn try_from(value: u16) -> Result<Self, Self::Error> {
174        match value {
175            437 => Ok(Codepage::CP437),
176            720 => Ok(Codepage::CP720),
177            737 => Ok(Codepage::CP737),
178            775 => Ok(Codepage::CP775),
179            850 => Ok(Codepage::CP850),
180            852 => Ok(Codepage::CP852),
181            855 => Ok(Codepage::CP855),
182            857 => Ok(Codepage::CP857),
183            858 => Ok(Codepage::CP858),
184            860 => Ok(Codepage::CP860),
185            861 => Ok(Codepage::CP861),
186            862 => Ok(Codepage::CP862),
187            863 => Ok(Codepage::CP863),
188            864 => Ok(Codepage::CP864),
189            865 => Ok(Codepage::CP865),
190            866 => Ok(Codepage::CP866),
191            869 => Ok(Codepage::CP869),
192            874 => Ok(Codepage::CP874),
193            _ => Err(()),
194        }
195    }
196}
197
198impl From<Codepage> for u16 {
199    fn from(value: Codepage) -> Self {
200        match value {
201            Codepage::CP437 => 437,
202            Codepage::CP720 => 720,
203            Codepage::CP737 => 737,
204            Codepage::CP775 => 775,
205            Codepage::CP850 => 850,
206            Codepage::CP852 => 852,
207            Codepage::CP855 => 855,
208            Codepage::CP857 => 857,
209            Codepage::CP858 => 858,
210            Codepage::CP860 => 860,
211            Codepage::CP861 => 861,
212            Codepage::CP862 => 862,
213            Codepage::CP863 => 863,
214            Codepage::CP864 => 864,
215            Codepage::CP865 => 865,
216            Codepage::CP866 => 866,
217            Codepage::CP869 => 869,
218            Codepage::CP874 => 874,
219        }
220    }
221}