Files
apple-encodings/src/mac_roman.rs
Claude Fable 5 4f1439af65 apple-encodings: initial commit (renamed from mac-encodings)
Bidirectional, emulator-grade conversion between classic Mac OS text
encodings and Unicode. Renamed at extraction-to-shared-crate time
(2026-07-19): consumers will be fsinspect, adx, and ad-decoder via git
dependencies on code.movq.us.
2026-07-19 13:35:48 -05:00

61 lines
2.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Mac OS Roman: the high half of the table and revision handling.
//!
//! The lower 128 byte values are identical to ASCII; only `0x80..=0xFF` carry
//! Mac-specific glyphs. The table below is the **post-Mac OS 8.5** revision
//! (byte `0xDB` is the Euro sign); [`MacRomanRevision::Classic`] swaps that one
//! slot back to the pre-8.5 currency sign. See `docs` in the consuming projects
//! for why revision pinning is per-encoding.
//!
//! Source: the Unicode Consortium `VENDORS/APPLE/ROMAN.TXT` mapping.
/// Unicode scalars for Mac OS Roman bytes `0x80..=0xFF` (post-8.5 revision).
///
/// Index `i` corresponds to byte value `0x80 + i` — e.g. index 0 is `0x80` → 'Ä'.
pub(crate) const MAC_ROMAN_HIGH: [char; 128] = [
'Ä', 'Å', 'Ç', 'É', 'Ñ', 'Ö', 'Ü', 'á', // 0x80-0x87
'à', 'â', 'ä', 'ã', 'å', 'ç', 'é', 'è', // 0x88-0x8F
'ê', 'ë', 'í', 'ì', 'î', 'ï', 'ñ', 'ó', // 0x90-0x97
'ò', 'ô', 'ö', 'õ', 'ú', 'ù', 'û', 'ü', // 0x98-0x9F
'†', '°', '¢', '£', '§', '•', '¶', 'ß', // 0xA0-0xA7
'®', '©', '™', '´', '¨', '≠', 'Æ', 'Ø', // 0xA8-0xAF
'∞', '±', '≤', '≥', '¥', 'µ', '∂', '∑', // 0xB0-0xB7
'∏', 'π', '∫', 'ª', 'º', 'Ω', 'æ', 'ø', // 0xB8-0xBF
'¿', '¡', '¬', '√', 'ƒ', '≈', '∆', '«', // 0xC0-0xC7
'»', '…', '\u{00A0}', 'À', 'Ã', 'Õ', 'Œ', 'œ', // 0xC8-0xCF
'', '—', '\u{201C}', '\u{201D}', '\u{2018}', '\u{2019}', '÷', '◊', // 0xD0-0xD7
'ÿ', 'Ÿ', '', '€', '', '', '\u{FB01}', '\u{FB02}', // 0xD8-0xDF (0xDB € post-8.5)
'‡', '·', '', '„', '‰', 'Â', 'Ê', 'Á', // 0xE0-0xE7
'Ë', 'È', 'Í', 'Î', 'Ï', 'Ì', 'Ó', 'Ô', // 0xE8-0xEF
'\u{F8FF}', 'Ò', 'Ú', 'Û', 'Ù', 'ı', 'ˆ', '˜', // 0xF0-0xF7 (0xF0 = Apple logo, PUA)
'¯', '˘', '˙', '˚', '¸', '˝', '˛', 'ˇ', // 0xF8-0xFF
];
/// Index of byte `0xDB`, the only slot that differs across the 8.5 revision.
const EURO_SLOT: usize = (0xDB - 0x80) as usize;
/// The pre-8.5 glyph at `0xDB`: CURRENCY SIGN.
const CLASSIC_CURRENCY: char = '\u{00A4}';
/// Which revision of Mac OS Roman to use.
///
/// The Mac OS 8.5 Euro update changed exactly one byte (`0xDB`). Defaults to
/// [`Modern`](MacRomanRevision::Modern); choose [`Classic`](MacRomanRevision::Classic)
/// for pre-8.5 / emulator fidelity.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum MacRomanRevision {
/// Mac OS 8.5 and later: `0xDB` is EURO SIGN (`U+20AC`).
#[default]
Modern,
/// Before Mac OS 8.5: `0xDB` is CURRENCY SIGN (`U+00A4`).
Classic,
}
/// The effective high-half table for `revision` (a cheap 512-byte stack copy).
pub(crate) fn high_table(revision: MacRomanRevision) -> [char; 128] {
let mut table = MAC_ROMAN_HIGH;
if revision == MacRomanRevision::Classic {
table[EURO_SLOT] = CLASSIC_CURRENCY;
}
table
}