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
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use crate::HeadWriter;
use std::borrow::Borrow;
use std::io;

/// Helper function for writing data (not necessarily stored in a `Record` instance)
/// to the FASTA format.
///
/// The header line may be supplied as either a `&[u8]` / `&str` header line,
/// or as separate ID and description parts in the form `(&[u8], Option<&[u8]>)`
/// or `(&str, Option<&str>)`.
#[inline]
pub fn write<W, H>(writer: W, head: H, seq: &[u8]) -> io::Result<()>
where
    W: io::Write,
    H: HeadWriter,
{
    write_iter(writer, head, Some(seq))
}

/// Helper function for writing data (not necessarily stored in a `Record` instance)
/// to the FASTA format. In contrast to [`write`](write()), this
/// function accepts a sequence iterator.
#[inline]
pub fn write_iter<W, H, S, L>(mut writer: W, head: H, seq: S) -> io::Result<()>
where
    W: io::Write,
    H: HeadWriter,
    S: IntoIterator<Item = L>,
    L: Borrow<[u8]>,
{
    write_head(&mut writer, head)?;
    write_seq_iter(writer, seq)
}

/// Writes data to the FASTA format. Wraps the sequence to produce multi-line FASTA
/// with a maximum width specified by the `wrap` parameter.
#[inline]
pub fn write_wrap<W, H>(mut writer: W, head: H, seq: &[u8], wrap: usize) -> io::Result<()>
where
    W: io::Write,
    H: HeadWriter,
{
    write_head(&mut writer, head)?;
    write_wrap_seq(writer, seq, wrap)
}

/// Writes data to the FASTA format. Wraps the sequence to produce multi-line FASTA
/// with a maximum width specified by the `wrap` parameter. Accepts a sequence
/// iterator.
#[inline]
pub fn write_wrap_iter<'a, W, H, S>(mut writer: W, head: H, seq: S, wrap: usize) -> io::Result<()>
where
    W: io::Write,
    H: HeadWriter,
    S: IntoIterator<Item = &'a [u8]>,
{
    write_head(&mut writer, head)?;
    write_wrap_seq_iter(writer, seq, wrap)
}

/// Writes only the sequence line.
#[inline]
pub fn write_head<W, H>(writer: W, head: H) -> io::Result<()>
where
    W: io::Write,
    H: HeadWriter,
{
    head.write_head(writer, b'>')
}

/// Writes only the sequence line.
#[inline]
pub fn write_seq<W>(writer: W, seq: &[u8]) -> io::Result<()>
where
    W: io::Write,
{
    write_seq_iter(writer, Some(seq))
}

/// Writes the sequence line, and wraps the output to a maximum width specified by `wrap`.
#[inline]
pub fn write_wrap_seq<W>(mut writer: W, seq: &[u8], wrap: usize) -> io::Result<()>
where
    W: io::Write,
{
    assert!(wrap > 0);
    for chunk in seq.chunks(wrap) {
        writer.write_all(chunk)?;
        writer.write_all(b"\n")?;
    }
    Ok(())
}

/// Writes the sequence line from an iterator of lines.
#[inline]
pub fn write_seq_iter<'a, W, S, L>(mut writer: W, seq: S) -> io::Result<()>
where
    W: io::Write,
    S: IntoIterator<Item = L>,
    L: Borrow<[u8]>,
{
    for line in seq {
        writer.write_all(line.borrow())?;
    }
    writer.write_all(b"\n")
}

/// Writes the sequence line from an iterator (such as `SeqLines`) and wraps the output
/// to a maximum width specified by `wrap`.
#[inline]
pub fn write_wrap_seq_iter<'a, W, S, L>(mut writer: W, seq: S, wrap: usize) -> io::Result<()>
where
    W: io::Write,
    S: IntoIterator<Item = L>,
    L: Borrow<[u8]>,
{
    assert!(wrap > 0);
    let mut n_line = 0;
    for line in seq {
        let mut chunk = line.borrow();
        loop {
            let remaining = wrap - n_line;
            if chunk.len() <= remaining {
                writer.write_all(chunk)?;
                n_line += chunk.len();
                break;
            }
            // chunk longer than line -> break
            let (line, rest) = chunk.split_at(remaining);
            chunk = rest;
            //  println!("write {:?}", line);
            writer.write_all(line)?;
            writer.write_all(b"\n")?;
            n_line = 0;
        }
    }
    writer.write_all(b"\n")
}