From 8fef33afc3cefdf7b9cec83019a4abac3c3e1cab Mon Sep 17 00:00:00 2001 From: Michael Macias Date: Sun, 5 Jan 2025 11:53:21 -0600 Subject: [PATCH] cram/io/reader/header/magic_number: Split read and validation --- noodles-cram/src/async/io/reader.rs | 6 ++- .../async/io/reader/header/magic_number.rs | 42 ++++++----------- noodles-cram/src/io/reader.rs | 4 +- noodles-cram/src/io/reader/header.rs | 2 +- .../src/io/reader/header/magic_number.rs | 45 +++++++++++-------- 5 files changed, 48 insertions(+), 51 deletions(-) diff --git a/noodles-cram/src/async/io/reader.rs b/noodles-cram/src/async/io/reader.rs index 6de85ac83..7b40929be 100644 --- a/noodles-cram/src/async/io/reader.rs +++ b/noodles-cram/src/async/io/reader.rs @@ -111,7 +111,11 @@ where /// # } /// ``` pub async fn read_file_definition(&mut self) -> io::Result { - header::read_magic_number(&mut self.inner).await?; + use crate::io::reader::header::magic_number; + + header::read_magic_number(&mut self.inner) + .await + .and_then(magic_number::validate)?; let format = read_format(&mut self.inner).await?; let file_id = read_file_id(&mut self.inner).await?; diff --git a/noodles-cram/src/async/io/reader/header/magic_number.rs b/noodles-cram/src/async/io/reader/header/magic_number.rs index 8aa3bd05c..4b714f410 100644 --- a/noodles-cram/src/async/io/reader/header/magic_number.rs +++ b/noodles-cram/src/async/io/reader/header/magic_number.rs @@ -1,22 +1,14 @@ use tokio::io::{self, AsyncRead, AsyncReadExt}; -pub(crate) async fn read_magic_number(reader: &mut R) -> io::Result<()> +use crate::MAGIC_NUMBER; + +pub(crate) async fn read_magic_number(reader: &mut R) -> io::Result<[u8; MAGIC_NUMBER.len()]> where R: AsyncRead + Unpin, { - use crate::MAGIC_NUMBER; - - let mut magic = [0; 4]; - reader.read_exact(&mut magic).await?; - - if magic == MAGIC_NUMBER { - Ok(()) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - "invalid CRAM header", - )) - } + let mut buf = [0; MAGIC_NUMBER.len()]; + reader.read_exact(&mut buf).await?; + Ok(buf) } #[cfg(test)] @@ -24,23 +16,17 @@ mod tests { use super::*; #[tokio::test] - async fn test_read_magic_number() { - let data = b"CRAM"; - let mut reader = &data[..]; - assert!(read_magic_number(&mut reader).await.is_ok()); + async fn test_read_magic_number() -> io::Result<()> { + let src = b"CRAM"; + let mut reader = &src[..]; + assert_eq!(read_magic_number(&mut reader).await?, *b"CRAM"); - let data = []; - let mut reader = &data[..]; + let mut src = &[][..]; assert!(matches!( - read_magic_number(&mut reader).await, - Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof + read_magic_number(&mut src).await, + Err(e) if e.kind() == io::ErrorKind::UnexpectedEof )); - let data = b"BAM\x01"; - let mut reader = &data[..]; - assert!(matches!( - read_magic_number(&mut reader).await, - Err(ref e) if e.kind() == io::ErrorKind::InvalidData - )); + Ok(()) } } diff --git a/noodles-cram/src/io/reader.rs b/noodles-cram/src/io/reader.rs index 71215af63..a0a667ca6 100644 --- a/noodles-cram/src/io/reader.rs +++ b/noodles-cram/src/io/reader.rs @@ -3,7 +3,7 @@ mod builder; pub(crate) mod container; pub(crate) mod data_container; -mod header; +pub(crate) mod header; pub(crate) mod header_container; pub(crate) mod num; mod query; @@ -128,7 +128,7 @@ where /// # Ok::<(), io::Error>(()) /// ``` pub fn read_file_definition(&mut self) -> io::Result { - header::read_magic_number(&mut self.inner)?; + header::read_magic_number(&mut self.inner).and_then(header::magic_number::validate)?; let format = read_format(&mut self.inner)?; let file_id = read_file_id(&mut self.inner)?; diff --git a/noodles-cram/src/io/reader/header.rs b/noodles-cram/src/io/reader/header.rs index 2abea9430..5d1484897 100644 --- a/noodles-cram/src/io/reader/header.rs +++ b/noodles-cram/src/io/reader/header.rs @@ -1,3 +1,3 @@ -mod magic_number; +pub(crate) mod magic_number; pub(super) use self::magic_number::read_magic_number; diff --git a/noodles-cram/src/io/reader/header/magic_number.rs b/noodles-cram/src/io/reader/header/magic_number.rs index 6e01d21a4..eba3617c3 100644 --- a/noodles-cram/src/io/reader/header/magic_number.rs +++ b/noodles-cram/src/io/reader/header/magic_number.rs @@ -2,14 +2,19 @@ use std::io::{self, Read}; use crate::MAGIC_NUMBER; -pub(crate) fn read_magic_number(reader: &mut R) -> io::Result<()> +type Buf = [u8; MAGIC_NUMBER.len()]; + +pub(crate) fn read_magic_number(reader: &mut R) -> io::Result where R: Read, { - let mut buf = [0; 4]; + let mut buf = [0; MAGIC_NUMBER.len()]; reader.read_exact(&mut buf)?; + Ok(buf) +} - if buf == MAGIC_NUMBER { +pub(crate) fn validate(buf: Buf) -> io::Result<()> { + if is_valid(buf) { Ok(()) } else { Err(io::Error::new( @@ -19,31 +24,33 @@ where } } +fn is_valid(buf: Buf) -> bool { + buf == MAGIC_NUMBER +} + #[cfg(test)] mod tests { use super::*; #[test] - fn test_read_magic_number() { - let data = b"CRAM"; - let mut reader = &data[..]; - assert!(read_magic_number(&mut reader).is_ok()); - } + fn test_read_magic_number() -> io::Result<()> { + let src = b"CRAM"; + let mut reader = &src[..]; + assert_eq!(read_magic_number(&mut reader)?, *b"CRAM"); - #[test] - fn test_read_magic_number_with_invalid_input() { - let data = []; - let mut reader = &data[..]; + let src = []; + let mut reader = &src[..]; assert!(matches!( read_magic_number(&mut reader), - Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof, + Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof )); - let data = b"BAM\x01"; - let mut reader = &data[..]; - assert!(matches!( - read_magic_number(&mut reader), - Err(ref e) if e.kind() == io::ErrorKind::InvalidData, - )); + Ok(()) + } + + #[test] + fn test_is_valid() { + assert!(is_valid(*b"CRAM")); + assert!(!is_valid([0x00, 0x00, 0x00, 0x00])); } }