crlify/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

//! [`BufWriterWithLineEndingFix`].

use std::io::{BufWriter, Result, Write};

/// A small helper class to convert LF to CRLF on Windows.
/// Workaround for <https://github.com/serde-rs/json/issues/535>
pub struct BufWriterWithLineEndingFix<W: Write> {
    inner: BufWriter<W>,
    #[cfg(windows)]
    last_written: Option<u8>,
}

impl<W: Write> BufWriterWithLineEndingFix<W> {
    pub fn new(inner: W) -> Self {
        Self {
            inner: BufWriter::with_capacity(4096, inner),
            #[cfg(windows)]
            last_written: None,
        }
    }
}

impl<W: Write> Write for BufWriterWithLineEndingFix<W> {
    #[cfg(windows)]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        for &b in buf.iter() {
            if b == b'\n' && self.last_written != Some(b'\r') {
                // Note: Since we need to emit the \r, we are adding extra bytes than were in
                // the input buffer. BufWriter helps because short writes (less than 4096 B)
                // will always write or fail in their entirety.
                self.inner.write(b"\r\n")
            } else {
                self.last_written = Some(b);
                self.inner.write(&[b])
            }?;
        }
        // The return value is the number of *input* bytes that were written.
        Ok(buf.len())
    }

    #[cfg(not(windows))]
    #[inline]
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.inner.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> Result<()> {
        self.inner.flush()
    }
}