crlify/lib.rs
1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5//! [`BufWriterWithLineEndingFix`].
6
7use std::io::{BufWriter, Result, Write};
8
9/// A small helper class to convert LF to CRLF on Windows.
10/// Workaround for <https://github.com/serde-rs/json/issues/535>
11pub struct BufWriterWithLineEndingFix<W: Write> {
12 inner: BufWriter<W>,
13 #[cfg(windows)]
14 last_written: Option<u8>,
15}
16
17impl<W: Write> BufWriterWithLineEndingFix<W> {
18 pub fn new(inner: W) -> Self {
19 Self {
20 inner: BufWriter::with_capacity(4096, inner),
21 #[cfg(windows)]
22 last_written: None,
23 }
24 }
25}
26
27impl<W: Write> Write for BufWriterWithLineEndingFix<W> {
28 #[cfg(windows)]
29 fn write(&mut self, buf: &[u8]) -> Result<usize> {
30 for &b in buf.iter() {
31 if b == b'\n' && self.last_written != Some(b'\r') {
32 // Note: Since we need to emit the \r, we are adding extra bytes than were in
33 // the input buffer. BufWriter helps because short writes (less than 4096 B)
34 // will always write or fail in their entirety.
35 self.inner.write(b"\r\n")
36 } else {
37 self.last_written = Some(b);
38 self.inner.write(&[b])
39 }?;
40 }
41 // The return value is the number of *input* bytes that were written.
42 Ok(buf.len())
43 }
44
45 #[cfg(not(windows))]
46 #[inline]
47 fn write(&mut self, buf: &[u8]) -> Result<usize> {
48 self.inner.write(buf)
49 }
50
51 #[inline]
52 fn flush(&mut self) -> Result<()> {
53 self.inner.flush()
54 }
55}