mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
group cp437 functions
This commit is contained in:
parent
dea176d0d9
commit
4f83aa3d5c
|
@ -1,57 +1,54 @@
|
||||||
//! Conversion between UTF-8 and CP-437.
|
|
||||||
//!
|
|
||||||
//! Most of the functionality is only available with feature "cp437" enabled.
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[allow(unused)] // depends on features
|
/// Contains functions to convert between UTF-8 and Codepage 437.
|
||||||
pub use feature_cp437::*;
|
///
|
||||||
|
/// See <https://en.wikipedia.org/wiki/Code_page_437#Character_set>
|
||||||
|
pub struct Cp437Converter;
|
||||||
|
|
||||||
#[cfg(feature = "cp437")]
|
/// An array of 256 elements, mapping most of the CP437 values to UTF-8 characters
|
||||||
mod feature_cp437 {
|
///
|
||||||
use super::*;
|
/// Mostly follows CP437, except 0x0A, which is kept for use as line ending.
|
||||||
|
///
|
||||||
/// An array of 256 elements, mapping most of the CP437 values to UTF-8 characters
|
/// See <https://en.wikipedia.org/wiki/Code_page_437#Character_set>
|
||||||
///
|
///
|
||||||
/// Mostly follows CP437, except 0x0A, which is kept for use as line ending.
|
/// Mostly copied from <https://github.com/kip93/cp437-tools>. License: GPL-3.0
|
||||||
///
|
#[rustfmt::skip]
|
||||||
/// See <https://en.wikipedia.org/wiki/Code_page_437#Character_set>
|
const CP437_TO_UTF8: [char; 256] = [
|
||||||
///
|
/* 0X */ '\0', '☺', '☻', '♥', '♦', '♣', '♠', '•', '◘', '○', '\n', '♂', '♀', '♪', '♫', '☼',
|
||||||
/// Mostly copied from <https://github.com/kip93/cp437-tools>. License: GPL-3.0
|
/* 1X */ '►', '◄', '↕', '‼', '¶', '§', '▬', '↨', '↑', '↓', '→', '←', '∟', '↔', '▲', '▼',
|
||||||
#[rustfmt::skip]
|
/* 2X */ ' ', '!', '"', '#', '$', '%', '&', '\'','(', ')', '*', '+', ',', '-', '.', '/',
|
||||||
pub const CP437_TO_UTF8: [char; 256] = [
|
/* 3X */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
|
||||||
/* 0X */ '\0', '☺', '☻', '♥', '♦', '♣', '♠', '•', '◘', '○', '\n', '♂', '♀', '♪', '♫', '☼',
|
/* 4X */ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||||
/* 1X */ '►', '◄', '↕', '‼', '¶', '§', '▬', '↨', '↑', '↓', '→', '←', '∟', '↔', '▲', '▼',
|
/* 5X */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\',']', '^', '_',
|
||||||
/* 2X */ ' ', '!', '"', '#', '$', '%', '&', '\'','(', ')', '*', '+', ',', '-', '.', '/',
|
/* 6X */ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||||
/* 3X */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
|
/* 7X */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '⌂',
|
||||||
/* 4X */ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
/* 8X */ 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
|
||||||
/* 5X */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\',']', '^', '_',
|
/* 9X */ 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', '¢', '£', '¥', '₧', 'ƒ',
|
||||||
/* 6X */ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
/* AX */ 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '⌐', '¬', '½', '¼', '¡', '«', '»',
|
||||||
/* 7X */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '⌂',
|
/* BX */ '░', '▒', '▓', '│', '┤', '╡', '╢', '╖', '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
|
||||||
/* 8X */ 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
|
/* CX */ '└', '┴', '┬', '├', '─', '┼', '╞', '╟', '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
|
||||||
/* 9X */ 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', '¢', '£', '¥', '₧', 'ƒ',
|
/* DX */ '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫', '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
|
||||||
/* AX */ 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '⌐', '¬', '½', '¼', '¡', '«', '»',
|
/* EX */ 'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ', 'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
|
||||||
/* BX */ '░', '▒', '▓', '│', '┤', '╡', '╢', '╖', '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
|
/* FX */ '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈', '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
|
||||||
/* CX */ '└', '┴', '┬', '├', '─', '┼', '╞', '╟', '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
|
];
|
||||||
/* DX */ '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫', '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
|
static UTF8_TO_CP437: once_cell::sync::Lazy<HashMap<char, u8>> =
|
||||||
/* EX */ 'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ', 'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
|
once_cell::sync::Lazy::new(|| {
|
||||||
/* FX */ '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈', '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
|
let pairs = CP437_TO_UTF8
|
||||||
];
|
.iter()
|
||||||
|
.enumerate()
|
||||||
static UTF8_TO_CP437: once_cell::sync::Lazy<HashMap<char, u8>> =
|
.map(move |(index, char)| (*char, index as u8));
|
||||||
once_cell::sync::Lazy::new(|| {
|
HashMap::from_iter(pairs)
|
||||||
let pairs = CP437_TO_UTF8
|
});
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(move |(index, char)| (*char, index as u8));
|
|
||||||
HashMap::from_iter(pairs)
|
|
||||||
});
|
|
||||||
|
|
||||||
|
impl Cp437Converter {
|
||||||
const MISSING_CHAR_CP437: u8 = 0x3F; // '?'
|
const MISSING_CHAR_CP437: u8 = 0x3F; // '?'
|
||||||
|
|
||||||
/// Convert the provided bytes to UTF-8.
|
/// Convert the provided bytes to UTF-8.
|
||||||
pub fn cp437_to_str(cp437: &[u8]) -> String {
|
pub fn cp437_to_str(cp437: &[u8]) -> String {
|
||||||
cp437.iter().map(move |char| cp437_to_char(*char)).collect()
|
cp437
|
||||||
|
.iter()
|
||||||
|
.map(move |char| Self::cp437_to_char(*char))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a single CP-437 character to UTF-8.
|
/// Convert a single CP-437 character to UTF-8.
|
||||||
|
@ -63,17 +60,18 @@ mod feature_cp437 {
|
||||||
///
|
///
|
||||||
/// Characters that are not available are mapped to '?'.
|
/// Characters that are not available are mapped to '?'.
|
||||||
pub fn str_to_cp437(utf8: &str) -> Vec<u8> {
|
pub fn str_to_cp437(utf8: &str) -> Vec<u8> {
|
||||||
utf8.chars().map(char_to_cp437).collect()
|
utf8.chars().map(Self::char_to_cp437).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a single UTF-8 character to CP-437.
|
/// Convert a single UTF-8 character to CP-437.
|
||||||
pub fn char_to_cp437(utf8: char) -> u8 {
|
pub fn char_to_cp437(utf8: char) -> u8 {
|
||||||
*UTF8_TO_CP437.get(&utf8).unwrap_or(&MISSING_CHAR_CP437)
|
*UTF8_TO_CP437
|
||||||
|
.get(&utf8)
|
||||||
|
.unwrap_or(&Self::MISSING_CHAR_CP437)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(feature = "cp437")]
|
|
||||||
mod tests_feature_cp437 {
|
mod tests_feature_cp437 {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -102,13 +100,16 @@ mod tests_feature_cp437 {
|
||||||
│dx ≡ Σ √x²ⁿ·δx
|
│dx ≡ Σ √x²ⁿ·δx
|
||||||
⌡"#;
|
⌡"#;
|
||||||
|
|
||||||
let cp437 = str_to_cp437(utf8);
|
let cp437 = Cp437Converter::str_to_cp437(utf8);
|
||||||
let actual = cp437_to_str(&*cp437);
|
let actual = Cp437Converter::cp437_to_str(&*cp437);
|
||||||
assert_eq!(utf8, actual)
|
assert_eq!(utf8, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn convert_invalid() {
|
fn convert_invalid() {
|
||||||
assert_eq!(cp437_to_char(char_to_cp437('😜')), '?');
|
assert_eq!(
|
||||||
|
Cp437Converter::cp437_to_char(Cp437Converter::char_to_cp437('😜')),
|
||||||
|
'?'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,20 +83,17 @@ pub use feature_cp437::*;
|
||||||
#[cfg(feature = "cp437")]
|
#[cfg(feature = "cp437")]
|
||||||
mod feature_cp437 {
|
mod feature_cp437 {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{CharGrid, Cp437Converter};
|
||||||
cp437::{char_to_cp437, cp437_to_char},
|
|
||||||
CharGrid,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl From<&Cp437Grid> for CharGrid {
|
impl From<&Cp437Grid> for CharGrid {
|
||||||
fn from(value: &Cp437Grid) -> Self {
|
fn from(value: &Cp437Grid) -> Self {
|
||||||
value.map(cp437_to_char)
|
value.map(Cp437Converter::cp437_to_char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&CharGrid> for Cp437Grid {
|
impl From<&CharGrid> for Cp437Grid {
|
||||||
fn from(value: &CharGrid) -> Self {
|
fn from(value: &CharGrid) -> Self {
|
||||||
value.map(char_to_cp437)
|
value.map(Cp437Converter::char_to_cp437)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ pub use crate::command::{Command, Offset};
|
||||||
pub use crate::compression_code::CompressionCode;
|
pub use crate::compression_code::CompressionCode;
|
||||||
pub use crate::connection::Connection;
|
pub use crate::connection::Connection;
|
||||||
pub use crate::constants::*;
|
pub use crate::constants::*;
|
||||||
|
pub use crate::cp437::Cp437Converter;
|
||||||
pub use crate::cp437_grid::Cp437Grid;
|
pub use crate::cp437_grid::Cp437Grid;
|
||||||
pub use crate::data_ref::DataRef;
|
pub use crate::data_ref::DataRef;
|
||||||
pub use crate::grid::Grid;
|
pub use crate::grid::Grid;
|
||||||
|
@ -66,7 +67,6 @@ mod compression;
|
||||||
mod compression_code;
|
mod compression_code;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod constants;
|
mod constants;
|
||||||
pub mod cp437;
|
|
||||||
mod cp437_grid;
|
mod cp437_grid;
|
||||||
mod data_ref;
|
mod data_ref;
|
||||||
mod grid;
|
mod grid;
|
||||||
|
@ -74,6 +74,9 @@ mod origin;
|
||||||
mod packet;
|
mod packet;
|
||||||
mod value_grid;
|
mod value_grid;
|
||||||
|
|
||||||
|
#[cfg(feature = "cp437")]
|
||||||
|
mod cp437;
|
||||||
|
|
||||||
// include README.md in doctest
|
// include README.md in doctest
|
||||||
#[doc = include_str!("../README.md")]
|
#[doc = include_str!("../README.md")]
|
||||||
#[cfg(doctest)]
|
#[cfg(doctest)]
|
||||||
|
|
Loading…
Reference in a new issue