fs_tail/
lib.rs

1use std::io::{BufReader, IoSliceMut, Read, BufRead, Error, ErrorKind, Seek, SeekFrom};
2use std::fs::File;
3use std::{io, fmt, result};
4use std::sync::{Mutex, Arc, MutexGuard};
5use std::thread::sleep;
6use std::time::Duration;
7
8
9enum Maybe<T> {
10    Real(T),
11}
12
13struct TailedFileRaw(BufReader<File>);
14// impl Read for buffreader
15pub struct TailedFile {
16    inner: Arc<Mutex<BufReader<Maybe<TailedFileRaw>>>>
17}
18
19impl TailedFile {
20    pub fn new(mut file: File) -> Self {
21        let _ = file.seek(SeekFrom::End(0));
22        let a  = BufReader::new(file);
23        TailedFile {
24            inner: Arc::new(Mutex::new(BufReader::with_capacity(10000, Maybe::Real(TailedFileRaw(a)))))
25        }
26
27    }
28    pub fn lock(&self) -> TailedFileLock<'_> {
29        TailedFileLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
30    }
31
32    /*
33    pub fn lock(&self) -> StdinLock<'_> {
34        StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
35    }
36     */
37}
38
39pub struct TailedFileLock<'a> {
40    inner: MutexGuard<'a, BufReader<Maybe<TailedFileRaw>>>,
41}
42
43impl fmt::Debug for TailedFileLock<'_> {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        f.pad("TailedFileLock { .. }")
46    }
47}
48
49impl BufRead for TailedFileLock<'_> {
50    fn fill_buf(&mut self) -> io::Result<&[u8]> {
51        self.inner.fill_buf()
52    }
53
54    fn consume(&mut self, n: usize) {
55        self.inner.consume(n)
56    }
57
58    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
59        self.inner.read_until(byte, buf)
60    }
61
62    fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
63// Note that we are not calling the `.read_until` method here, but
64        // rather our hardcoded implementation. For more details as to why, see
65        // the comments in `read_to_end`.
66        append_to_string(buf, |b| read_until(self, b'\n', b))
67
68    }
69}
70
71fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> Result<usize> {
72    let mut read = 0;
73    loop {
74        let (done, used) = {
75            let available = match r.fill_buf() {
76                Ok(n) if !n.is_empty() => n,
77                Err(ref e) if e.kind() == ErrorKind::Interrupted => {sleep(Duration::from_millis(1)); continue;},
78                Err(e) => return Err(e),
79                _ => {continue}
80            };
81            match memchr::memchr(delim, available) {
82                Some(i) => {
83                    buf.extend_from_slice(&available[..=i]);
84                    (true, i + 1)
85                }
86                None => {
87                    buf.extend_from_slice(available);
88                    (false, available.len())
89                }
90            }
91        };
92        r.consume(used);
93        read += used;
94        if done || used == 0 {
95            return Ok(read);
96        }
97    }
98}
99
100struct Guard<'a> {
101    buf: &'a mut Vec<u8>,
102    len: usize,
103}
104
105impl Drop for Guard<'_> {
106    fn drop(&mut self) {
107        unsafe {
108            self.buf.set_len(self.len);
109        }
110    }
111}
112
113
114pub type Result<T> = result::Result<T, Error>;
115fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
116    where
117        F: FnOnce(&mut Vec<u8>) -> Result<usize>,
118{
119    unsafe {
120        let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
121        let ret = f(g.buf);
122        if std::str::from_utf8(&g.buf[g.len..]).is_err() {
123            ret.and_then(|_| {
124                Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8"))
125            })
126        } else {
127            g.len = g.buf.len();
128            ret
129        }
130    }
131}
132
133impl Read for TailedFileLock<'_> {
134    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
135        self.inner.read(buf)
136    }
137
138    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
139        self.inner.read_vectored(bufs)
140    }
141
142    // #[inline]
143    // fn is_read_vectored(&self) -> bool {
144    //     self.inner.is_read_vectored()
145    // }
146
147
148
149    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
150        self.inner.read_to_end(buf)
151    }
152
153    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
154        self.inner.read_to_string(buf)
155    }
156
157    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
158        self.inner.read_exact(buf)
159    }
160}
161
162impl Read for TailedFileRaw {
163    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
164        self.0.read(buf)
165    }
166
167    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
168        self.0.read_vectored(bufs)
169    }
170
171    // #[inline]
172    // fn is_read_vectored(&self) -> bool {
173    //     self.0.is_read_vectored()
174    // }
175
176    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
177        self.0.read_to_end(buf)
178    }
179
180    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
181        self.0.read_to_string(buf)
182    }
183
184    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
185        self.0.read_exact(buf)
186    }
187}
188
189impl<R: io::Read> io::Read for Maybe<R> {
190    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
191        match *self {
192            Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
193        }
194    }
195
196    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
197        match self {
198            Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
199        }
200    }
201
202}
203
204fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
205
206    match r {
207        // Err(ref e) if stdio::is_ebadf(e) => Ok(default),
208        Err(ref _e) => Ok(default),
209        r => r,
210    }
211}