atglib/bed/
writer.rs

1use std::fs::File;
2use std::io::{BufWriter, Write};
3use std::path::Path;
4
5use crate::bed::BedLine;
6use crate::models::{Transcript, TranscriptWrite};
7use crate::utils::errors::ParseBedError;
8use crate::utils::errors::ReadWriteError;
9
10/// Writes [`Transcript`]s into a `BufWriter`
11///
12/// # Examples
13///
14/// ```rust
15/// use std::io;
16/// use atglib::tests;;
17/// use atglib::bed::Writer;
18/// use atglib::models::TranscriptWrite;
19///
20/// let transcripts = vec![tests::transcripts::standard_transcript()];
21///
22/// let output = Vec::new(); // substitute this with proper IO (io::stdout())
23/// let mut writer = Writer::new(output);
24/// writer.write_transcript_vec(&transcripts);
25///
26/// let written_output = String::from_utf8(writer.into_inner().unwrap()).unwrap();
27/// assert_eq!(written_output.starts_with("chr1\t"), true);
28/// ```
29pub struct Writer<W: std::io::Write> {
30    inner: BufWriter<W>,
31}
32
33impl Writer<File> {
34    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, ReadWriteError> {
35        match File::create(path.as_ref()) {
36            Ok(file) => Ok(Self::new(file)),
37            Err(err) => Err(ReadWriteError::new(err)),
38        }
39    }
40}
41
42impl<W: std::io::Write> Writer<W> {
43    /// Creates a new generic Writer for any `std::io::Read`` object
44    ///
45    /// Use this method when you want to write to stdout or
46    /// a remote source, e.g. via HTTP
47    pub fn new(writer: W) -> Self {
48        Writer {
49            inner: BufWriter::new(writer),
50        }
51    }
52
53    pub fn with_capacity(capacity: usize, writer: W) -> Self {
54        Writer {
55            inner: BufWriter::with_capacity(capacity, writer),
56        }
57    }
58
59    pub fn flush(&mut self) -> Result<(), ParseBedError> {
60        match self.inner.flush() {
61            Ok(res) => Ok(res),
62            Err(err) => Err(ParseBedError::from(err.to_string())),
63        }
64    }
65
66    pub fn into_inner(self) -> Result<W, ParseBedError> {
67        match self.inner.into_inner() {
68            Ok(res) => Ok(res),
69            Err(err) => Err(ParseBedError::from(err.to_string())),
70        }
71    }
72}
73
74impl<W: std::io::Write> TranscriptWrite for Writer<W> {
75    /// Writes a single transcript formatted as RefGene with an extra newline
76    ///
77    /// This method adds an extra newline at the end of the row
78    /// to allow writing multiple transcripts continuosly
79    fn writeln_single_transcript(&mut self, transcript: &Transcript) -> Result<(), std::io::Error> {
80        self.write_single_transcript(transcript)?;
81        self.inner.write_all("\n".as_bytes())
82    }
83
84    fn write_single_transcript(&mut self, transcript: &Transcript) -> Result<(), std::io::Error> {
85        self.inner
86            .write_all(BedLine::from(transcript).to_string().as_bytes())
87    }
88}