utf16_ext/
auto.rs

1use *;
2use byteorder::{LE, BE};
3
4use std::io::{Error, ErrorKind};
5
6/// A writer that will store whether to write in little or big endian
7pub enum AutoWriter<W> {
8    /// Little endian writer
9    Little(W),
10    /// Big endian writer
11    Big(W)
12}
13
14/// A reader that will store whether to read in little or big endian
15pub enum AutoEndianReader<R> {
16    /// Little endian reader
17    Little(R),
18    /// Big endian reader
19    Big(R)
20}
21
22/// An iterator over `char`s from an `AutoEndianReader`
23pub enum AutoEndianChars<R> {
24    /// Little endian reader
25    Little(Chars<LE, R>),
26    /// Big endian reader
27    Big(Chars<BE, R>)
28}
29
30/// An iterator over `u16`s from an `AutoEndianReader`
31pub enum AutoEndianShorts<R> {
32    /// Little endian reader
33    Little(Shorts<LE, R>),
34    /// Big endian reader
35    Big(Shorts<BE, R>)
36}
37
38/// An iterator over lines from an `AutoEndianReader`
39pub enum AutoEndianLines<R> {
40    /// Little endian reader
41    Little(Lines<LE, R>),
42    /// Big endian reader
43    Big(Lines<BE, R>)
44}
45
46impl<R> AutoEndianReader<R> {
47    /// Makes a new `AutoEndianReader` in little endian
48    pub fn new_little(inner: R) -> Self {
49        AutoEndianReader::Little(inner)
50    }
51    /// Makes a new `AutoEndianReader` in big endian
52    pub fn new_big(inner: R) -> Self {
53        AutoEndianReader::Big(inner)
54    }
55    /// Returns true if this reader is little endian
56    pub fn is_little(&self) -> bool {
57        match *self {
58            AutoEndianReader::Little(_) => true,
59            _ => false,
60        }
61    }
62    /// Returns true if this reader is big endian
63    pub fn is_big(&self) -> bool {
64        match *self {
65            AutoEndianReader::Big(_) => true,
66            _ => false,
67        }
68    }
69}
70
71impl<R: Utf16ReadExt> AutoEndianReader<R> {
72    /// Reads a `u16` to detect the endianness
73    ///
74    /// If the value isn't a valid bom (U+FEFF), an error is thrown
75    pub fn new_auto_bom(mut inner: R) -> Result<Self, Error> {
76        let bom = inner.read_u16::<LE>()?;
77        match bom {
78            0xfeff => Ok(AutoEndianReader::Little(inner)),
79            0xfffe => Ok(AutoEndianReader::Big(inner)),
80            _ => Err(Error::new(ErrorKind::InvalidData, "First character wasn't a bom"))
81        }
82    }
83    /// Mirror of `Utf16ReadExt::read_u16` without the type parameter for endianness
84    pub fn read_u16(&mut self) -> Result<u16, Error> {
85        match *self {
86            AutoEndianReader::Little(ref mut r) => r.read_u16::<LE>(),
87            AutoEndianReader::Big(ref mut r) => r.read_u16::<BE>(),
88        }
89    }
90    /// Mirror of `Utf16ReadExt::shorts` without the type parameter for endianness
91    pub fn shorts(self) -> AutoEndianShorts<R>
92    where Self: Sized {
93        match self {
94            AutoEndianReader::Little(r) => AutoEndianShorts::Little(r.shorts::<LE>()),
95            AutoEndianReader::Big(r) => AutoEndianShorts::Big(r.shorts::<BE>()),
96        }
97    }
98    /// Mirror of `Utf16ReadExt::utf16_chars` without the type parameter for endianness
99    pub fn utf16_chars(self) -> AutoEndianChars<R>
100    where Self: Sized {
101        match self {
102            AutoEndianReader::Little(r) => AutoEndianChars::Little(r.utf16_chars()),
103            AutoEndianReader::Big(r) => AutoEndianChars::Big(r.utf16_chars()),
104        }
105    }
106    /// Mirror of `Utf16ReadExt::read_utf16_line` without the type parameter for endianness
107    pub fn read_utf16_line(&mut self, buf: &mut String) -> Result<usize, Error> {
108        match *self {
109            AutoEndianReader::Little(ref mut r) => r.read_utf16_line::<LE>(buf),
110            AutoEndianReader::Big(ref mut r) => r.read_utf16_line::<BE>(buf),
111        }
112    }
113    /// Mirror of `Utf16ReadExt::utf16_lines` without the type parameter for endianness
114    pub fn utf16_lines(self) -> AutoEndianLines<R>
115    where Self: Sized {
116        match self {
117            AutoEndianReader::Little(r) => AutoEndianLines::Little(r.utf16_lines()),
118            AutoEndianReader::Big(r) => AutoEndianLines::Big(r.utf16_lines()),
119        }
120    }
121}
122
123impl<R: Utf16ReadExt> Iterator for AutoEndianChars<R> {
124    type Item = Result<char, Error>;
125    fn next(&mut self) -> Option<Self::Item> {
126        match *self {
127            AutoEndianChars::Little(ref mut r) => r.next(),
128            AutoEndianChars::Big(ref mut r) => r.next(),
129        }
130    }
131}
132
133impl<R: Utf16ReadExt> Iterator for AutoEndianShorts<R> {
134    type Item = Result<u16, Error>;
135    fn next(&mut self) -> Option<Self::Item> {
136        match *self {
137            AutoEndianShorts::Little(ref mut r) => r.next(),
138            AutoEndianShorts::Big(ref mut r) => r.next(),
139        }
140    }
141}
142
143impl<R: Utf16ReadExt> Iterator for AutoEndianLines<R> {
144    type Item = Result<String, Error>;
145    fn next(&mut self) -> Option<Self::Item> {
146        match *self {
147            AutoEndianLines::Little(ref mut r) => r.next(),
148            AutoEndianLines::Big(ref mut r) => r.next(),
149        }
150    }
151}
152
153impl<W: Utf16WriteExt> AutoWriter<W> {
154    /// Writes a BOM in the writer and returns a new `AutoWriter` in little endian
155    pub fn new_little(mut writer: W) -> Result<Self, Error> {
156        writer.write_bom::<LE>()?;
157        Ok(AutoWriter::Little(writer))
158    }
159    /// Writes a BOM in the writer and returns a new `AutoWriter` in big endian
160    pub fn new_big(mut writer: W) -> Result<Self, Error> {
161        writer.write_bom::<BE>()?;
162        Ok(AutoWriter::Big(writer))
163    }
164    /// Mirror of `Utf16WriteExt::write_shorts` without the type parameter for endianness
165    pub fn write_shorts(&mut self, buf: &[u16]) -> Result<usize, Error> {
166        match *self {
167            AutoWriter::Little(ref mut w) => w.write_shorts::<LE>(buf),
168            AutoWriter::Big(ref mut w) => w.write_shorts::<BE>(buf)
169        }
170    }
171    /// Mirror of `Utf16WriteExt::write_all_shorts` without the type parameter for endianness
172    pub fn write_all_shorts(&mut self, buf: &[u16]) -> Result<(), Error> {
173        match *self {
174            AutoWriter::Little(ref mut w) => w.write_all_shorts::<LE>(buf),
175            AutoWriter::Big(ref mut w) => w.write_all_shorts::<BE>(buf)
176        }
177    }
178    /// Mirror of `Utf16WriteExt::write_utf16_string` without the type parameter for endianness
179    pub fn write_utf16_string<'a>(&mut self, s: &'a str) -> Result<Utf16Written<'a>, Error> {
180        match *self {
181            AutoWriter::Little(ref mut w) => w.write_utf16_string::<LE>(s),
182            AutoWriter::Big(ref mut w) => w.write_utf16_string::<BE>(s)
183        }
184    }
185}