Skip to content

Commit

Permalink
sam/lazy/record: Add wrapper for mapping quality
Browse files Browse the repository at this point in the history
  • Loading branch information
zaeleus committed Dec 14, 2023
1 parent d7150f6 commit c790016
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 14 deletions.
5 changes: 5 additions & 0 deletions noodles-sam/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

### Added

* sam/lazy/record: Add wrapper for mapping quality
(`lazy::Record::mapping_quality`).

### Changed

* sam: Raise minimum supported Rust version (MSRV) to 1.70.0.
Expand Down
21 changes: 12 additions & 9 deletions noodles-sam/src/lazy/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod bounds;
mod cigar;
mod data;
mod flags;
mod mapping_quality;
mod position;
mod quality_scores;
mod reference_sequence_name;
Expand All @@ -11,10 +12,10 @@ use std::{fmt, io};

use self::bounds::Bounds;
pub use self::{
cigar::Cigar, data::Data, flags::Flags, position::Position, quality_scores::QualityScores,
reference_sequence_name::ReferenceSequenceName, sequence::Sequence,
cigar::Cigar, data::Data, flags::Flags, mapping_quality::MappingQuality, position::Position,
quality_scores::QualityScores, reference_sequence_name::ReferenceSequenceName,
sequence::Sequence,
};
use crate::record::MappingQuality;

const MISSING: &[u8] = b"*";

Expand Down Expand Up @@ -101,13 +102,15 @@ impl Record {
/// ```
/// use noodles_sam as sam;
/// let record = sam::lazy::Record::default();
/// assert!(record.mapping_quality()?.is_none());
/// # Ok::<_, std::io::Error>(())
/// assert!(record.mapping_quality().is_none());
/// ```
pub fn mapping_quality(&self) -> io::Result<Option<MappingQuality>> {
use crate::reader::record::parse_mapping_quality;
let src = &self.buf[self.bounds.mapping_quality_range()];
parse_mapping_quality(src).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
pub fn mapping_quality(&self) -> Option<MappingQuality<'_>> {
const MISSING: &[u8] = b"255";

match &self.buf[self.bounds.mapping_quality_range()] {
MISSING => None,
buf => Some(MappingQuality::new(buf)),
}
}

/// Returns the CIGAR operations.
Expand Down
36 changes: 36 additions & 0 deletions noodles-sam/src/lazy/record/mapping_quality.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::io;

/// Raw SAM record mapping quality.
#[derive(Debug, Eq, PartialEq)]
pub struct MappingQuality<'a>(&'a [u8]);

impl<'a> MappingQuality<'a> {
pub(super) fn new(buf: &'a [u8]) -> Self {
Self(buf)
}
}

impl<'a> AsRef<[u8]> for MappingQuality<'a> {
fn as_ref(&self) -> &[u8] {
self.0
}
}

impl<'a> TryFrom<MappingQuality<'a>> for u8 {
type Error = io::Error;

fn try_from(raw_mapping_quality: MappingQuality<'a>) -> Result<Self, Self::Error> {
lexical_core::parse(raw_mapping_quality.as_ref())
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
}

impl<'a> TryFrom<MappingQuality<'a>> for crate::record::MappingQuality {
type Error = io::Error;

fn try_from(raw_mapping_quality: MappingQuality<'a>) -> Result<Self, Self::Error> {
u8::try_from(raw_mapping_quality).and_then(|n| {
Self::try_from(n).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
})
}
}
9 changes: 5 additions & 4 deletions noodles-sam/src/reader/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ mod sequence;
mod template_length;

pub(crate) use self::{
cigar::parse_cigar, flags::parse_flags, mapping_quality::parse_mapping_quality,
sequence::parse_sequence, template_length::parse_template_length,
cigar::parse_cigar, flags::parse_flags, sequence::parse_sequence,
template_length::parse_template_length,
};

use std::{
Expand All @@ -20,8 +20,9 @@ use std::{
};

use self::{
data::parse_data, position::parse_alignment_start, quality_scores::parse_quality_scores,
read_name::parse_read_name, reference_sequence_id::parse_reference_sequence_id,
data::parse_data, mapping_quality::parse_mapping_quality, position::parse_alignment_start,
quality_scores::parse_quality_scores, read_name::parse_read_name,
reference_sequence_id::parse_reference_sequence_id,
};
use super::read_line;
use crate::{alignment::Record, Header};
Expand Down
2 changes: 1 addition & 1 deletion noodles-sam/src/reader/record/mapping_quality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl fmt::Display for ParseError {
}
}

pub(crate) fn parse_mapping_quality(src: &[u8]) -> Result<Option<MappingQuality>, ParseError> {
pub(super) fn parse_mapping_quality(src: &[u8]) -> Result<Option<MappingQuality>, ParseError> {
lexical_core::parse(src)
.map_err(ParseError::Invalid)
.map(MappingQuality::new)
Expand Down

0 comments on commit c790016

Please sign in to comment.