noodles_bcf/io/reader/header/
vcf_header.rs1use std::io::{self, BufRead, BufReader, Read, Take};
4
5pub struct Reader<R> {
7 inner: BufReader<Take<R>>,
8 is_eol: bool,
9}
10
11impl<R> Reader<R>
12where
13 R: Read,
14{
15 pub(super) fn new(inner: R, len: u64) -> Self {
16 Self {
17 inner: BufReader::new(inner.take(len)),
18 is_eol: true,
19 }
20 }
21
22 pub fn discard_to_end(&mut self) -> io::Result<usize> {
24 let mut n = 0;
25
26 loop {
27 let src = self.inner.fill_buf()?;
28
29 if src.is_empty() {
30 return Ok(n);
31 }
32
33 let len = src.len();
34
35 self.inner.consume(len);
36
37 n += len;
38 }
39 }
40}
41
42impl<R> Read for Reader<R>
43where
44 R: Read,
45{
46 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
47 let mut src = self.fill_buf()?;
48 let amt = src.read(buf)?;
49
50 if !src.is_empty() {
51 self.is_eol = false;
52 }
53
54 self.consume(amt);
55
56 Ok(amt)
57 }
58}
59
60impl<R> BufRead for Reader<R>
61where
62 R: Read,
63{
64 fn fill_buf(&mut self) -> io::Result<&[u8]> {
65 use memchr::memchr;
66
67 const NUL: u8 = 0x00;
68 const LINE_FEED: u8 = b'\n';
69
70 let src = self.inner.fill_buf()?;
71
72 let buf = if self.is_eol && src.first().map(|&b| b == NUL).unwrap_or(true) {
73 &[]
74 } else if let Some(i) = memchr(LINE_FEED, src) {
75 self.is_eol = true;
76 &src[..=i]
77 } else {
78 self.is_eol = false;
79 src
80 };
81
82 Ok(buf)
83 }
84
85 fn consume(&mut self, amt: usize) {
86 self.inner.consume(amt);
87 }
88}