codepage_437/decode.rs
1use self::super::Cp437Dialect;
2use std::iter::FromIterator;
3use std::borrow::Cow;
4use std::str;
5
6
7/// Move data encoded in cp437 to a Unicode container of the specified type.
8///
9/// # Examples
10///
11/// ```
12/// # use codepage_437::{CP437_CONTROL, FromCp437};
13/// let cp437 = vec![0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x6E, 0x65, 0x77, 0x73, 0x20, 0x72, 0x65,
14/// 0x70, 0x6F, 0x72, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
15/// 0x65, 0x20, 0x9E, 0xAB, 0x20, 0x6D, 0x69, 0x6C, 0x6C, 0x69, 0x6F, 0x6E, 0x20,
16/// 0x41, 0x69, 0x72, 0x20, 0x4D, 0x65, 0x6C, 0x61, 0x6E, 0x65, 0x73, 0x69, 0x91,
17/// 0x20, 0x61, 0x69, 0x72, 0x63, 0x72, 0x61, 0x66, 0x74, 0x20, 0x68, 0x61, 0x73,
18/// 0x20, 0x63, 0x72, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73,
19/// 0x20, 0x6D, 0x6F, 0x72, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x72, 0x6F, 0x75,
20/// 0x6E, 0x64, 0x20, 0x39, 0x3A, 0x30, 0x30, 0x61, 0x6D, 0x2E];
21/// let unicode = "Local news reports that the ₧½ million Air Melanesiæ aircraft has crashed this morning around 9:00am.";
22///
23/// assert_eq!(String::from_cp437(cp437, &CP437_CONTROL), unicode); // cp437 is moved out of
24/// ```
25pub trait FromCp437<T: Sized> {
26 /// Do the conversion.
27 fn from_cp437(cp437: T, dialect: &Cp437Dialect) -> Self;
28}
29
30macro_rules! from_cp437_slice_impl {
31 ($($l:expr)*) => ($(
32 impl FromCp437<[u8; $l]> for String {
33 fn from_cp437(cp437: [u8; $l], dialect: &Cp437Dialect) -> Self {
34 from_cp437_slice_impl(&cp437, dialect)
35 }
36 }
37 )*)
38}
39
40impl FromCp437<Vec<u8>> for String {
41 fn from_cp437(cp437: Vec<u8>, dialect: &Cp437Dialect) -> Self {
42 if cp437.iter().all(|&b| dialect.overlap_cp437(b)) {
43 String::from_utf8(cp437).unwrap()
44 } else {
45 String::from_iter(cp437.into_iter().map(|b| dialect.decode(b)))
46 }
47 }
48}
49
50impl FromCp437<[u8; 0]> for String {
51 fn from_cp437(_: [u8; 0], _: &Cp437Dialect) -> Self {
52 String::new()
53 }
54}
55
56from_cp437_slice_impl!( 1 2 3 4 5 6 7 8 9
57 10 11 12 13 14 15 16 17 18 19
58 20 21 22 23 24 25 26 27 28 29
59 30 31 32);
60
61fn from_cp437_slice_impl(cp437: &[u8], dialect: &Cp437Dialect) -> String {
62 if cp437.iter().all(|&b| dialect.overlap_cp437(b)) {
63 String::from_utf8(cp437.to_vec()).unwrap()
64 } else {
65 String::from_iter(cp437.iter().map(|&b| dialect.decode(b)))
66 }
67}
68
69
70/// Try to borrow data encoded in cp437 as a Unicode container of the specified type.
71///
72/// If that cannot be done, clone it.
73///
74/// # Examples
75///
76/// ```
77/// # use codepage_437::{CP437_CONTROL, BorrowFromCp437};
78/// # use std::borrow::Cow;
79/// let cp437 = [0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x6E, 0x65, 0x77, 0x73, 0x20, 0x72, 0x65,
80/// 0x70, 0x6F, 0x72, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
81/// 0x65, 0x20, 0x9E, 0xAB, 0x20, 0x6D, 0x69, 0x6C, 0x6C, 0x69, 0x6F, 0x6E, 0x20,
82/// 0x41, 0x69, 0x72, 0x20, 0x4D, 0x65, 0x6C, 0x61, 0x6E, 0x65, 0x73, 0x69, 0x91,
83/// 0x20, 0x61, 0x69, 0x72, 0x63, 0x72, 0x61, 0x66, 0x74, 0x20, 0x68, 0x61, 0x73,
84/// 0x20, 0x63, 0x72, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73,
85/// 0x20, 0x6D, 0x6F, 0x72, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x72, 0x6F, 0x75,
86/// 0x6E, 0x64, 0x20, 0x39, 0x3A, 0x30, 0x30, 0x61, 0x6D, 0x2E];
87/// let unicode = "Local news reports that the ₧½ million Air Melanesiæ aircraft has crashed this morning around 9:00am.";
88///
89/// assert_eq!(Cow::borrow_from_cp437(&cp437[..], &CP437_CONTROL),
90/// String::borrow_from_cp437(&cp437[..], &CP437_CONTROL));
91/// assert_eq!(Cow::borrow_from_cp437(&cp437[..], &CP437_CONTROL), unicode);
92/// ```
93pub trait BorrowFromCp437<'c, T: ?Sized> {
94 /// Do the conversion.
95 fn borrow_from_cp437(cp437: &'c T, dialect: &Cp437Dialect) -> Self;
96}
97
98impl<'c, T: AsRef<[u8]> + ?Sized> BorrowFromCp437<'c, T> for Cow<'c, str> {
99 fn borrow_from_cp437(cp437: &'c T, dialect: &Cp437Dialect) -> Self {
100 borrow_from_cp437_cow_slice_impl(cp437.as_ref(), dialect)
101 }
102}
103
104impl<'c, T: AsRef<[u8]> + ?Sized> BorrowFromCp437<'c, T> for String {
105 fn borrow_from_cp437(cp437: &'c T, dialect: &Cp437Dialect) -> Self {
106 borrow_from_cp437_string_slice_impl(cp437.as_ref(), dialect)
107 }
108}
109
110fn borrow_from_cp437_cow_slice_impl<'c>(cp437: &'c [u8], dialect: &Cp437Dialect) -> Cow<'c, str> {
111 if cp437.iter().all(|&b| dialect.overlap_cp437(b)) {
112 Cow::Borrowed(str::from_utf8(&cp437[..]).unwrap())
113 } else {
114 Cow::Owned(String::from_iter(cp437.iter().map(|&b| dialect.decode(b))))
115 }
116}
117
118fn borrow_from_cp437_string_slice_impl(cp437: &[u8], dialect: &Cp437Dialect) -> String {
119 if cp437.iter().all(|&b| dialect.overlap_cp437(b)) {
120 String::from_utf8(cp437.to_vec()).unwrap()
121 } else {
122 String::from_iter(cp437.iter().map(|&b| dialect.decode(b)))
123 }
124}