Skip to main content

escriba_buffer/
line_ending.rs

1use serde::{Deserialize, Serialize};
2
3/// Line-ending flavor — preserved across save roundtrips.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
5pub enum LineEnding {
6    #[default]
7    Lf,
8    Crlf,
9    Cr,
10}
11
12impl LineEnding {
13    #[must_use]
14    pub const fn as_str(self) -> &'static str {
15        match self {
16            Self::Lf => "\n",
17            Self::Crlf => "\r\n",
18            Self::Cr => "\r",
19        }
20    }
21
22    /// Detect from a sample. LF wins in ties — fewer bytes, more common.
23    #[must_use]
24    pub fn detect(src: &str) -> Self {
25        let crlf = src.matches("\r\n").count();
26        if crlf > 0 {
27            return Self::Crlf;
28        }
29        if src.contains('\r') {
30            return Self::Cr;
31        }
32        Self::Lf
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn detect_defaults() {
42        assert_eq!(LineEnding::detect(""), LineEnding::Lf);
43        assert_eq!(LineEnding::detect("a\nb\nc"), LineEnding::Lf);
44        assert_eq!(LineEnding::detect("a\r\nb\r\nc"), LineEnding::Crlf);
45        assert_eq!(LineEnding::detect("a\rb\rc"), LineEnding::Cr);
46    }
47}