1use std::fmt;
2
3pub type Result<T> = std::result::Result<T, FastqError>;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct FastqPosition {
13 pub byte_offset: u64,
15 pub record_index: u64,
17 pub line_index: u8,
19}
20
21impl FastqPosition {
22 pub const fn new(byte_offset: u64, record_index: u64, line_index: u8) -> Self {
24 Self {
25 byte_offset,
26 record_index,
27 line_index,
28 }
29 }
30}
31
32impl fmt::Display for FastqPosition {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(
35 f,
36 "byte {}, record {}, line {}",
37 self.byte_offset, self.record_index, self.line_index
38 )
39 }
40}
41
42#[derive(Debug)]
44#[non_exhaustive]
45pub enum FastqError {
46 Io(std::io::Error),
48 Format(String),
50 FormatAt {
52 message: String,
54 position: FastqPosition,
56 },
57 Bgzf(String),
59 RecordTooLarge {
61 slab_size: usize,
63 },
64}
65
66impl fmt::Display for FastqError {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 match self {
69 Self::Io(err) => write!(f, "I/O error: {err}"),
70 Self::Format(msg) => write!(f, "parse error: {msg}"),
71 Self::FormatAt { message, position } => {
72 write!(f, "parse error at {position}: {message}")
73 }
74 Self::Bgzf(msg) => write!(f, "BGZF error: {msg}"),
75 Self::RecordTooLarge { slab_size } => {
76 write!(f, "record exceeds slab size ({slab_size} bytes)")
77 }
78 }
79 }
80}
81
82impl std::error::Error for FastqError {
83 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
84 match self {
85 Self::Io(err) => Some(err),
86 Self::Format(_)
87 | Self::FormatAt { .. }
88 | Self::Bgzf(_)
89 | Self::RecordTooLarge { .. } => None,
90 }
91 }
92}
93
94impl From<std::io::Error> for FastqError {
95 fn from(value: std::io::Error) -> Self {
96 Self::Io(value)
97 }
98}