Skip to content

Commit

Permalink
cargo fmt, docs, examples
Browse files Browse the repository at this point in the history
  • Loading branch information
bsaintjo committed Dec 27, 2022
1 parent cbc2be9 commit a7a0696
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 57 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- aux: Removed the `to_slow5_t` required method on `AuxField` since it wasn't necessary and making dealing with enums harder


### Fixed

- mem: Fixed potential memory leaks during error paths

## [0.9.0] - 2022-12-10

### Added
Expand Down
4 changes: 2 additions & 2 deletions tests/read_blow5.rs → examples/read_blow5.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use slow5::{FileReader, RecordExt};

#[test]
fn main() -> anyhow::Result<()> {
let file_path = "examples/example3.blow5";
let mut slow5 = FileReader::open(file_path)?;
let mut records = slow5.records();
while let Some(Ok(rec)) = records.next() {
println!("{:?}", rec.read_id());
let id = std::str::from_utf8(rec.read_id())?;
println!("{id}");
}
Ok(())
}
2 changes: 1 addition & 1 deletion examples/slow5-serde/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use slow5::FileReader;

fn main() -> anyhow::Result<()>{
fn main() -> anyhow::Result<()> {
let mut reader = FileReader::open("examples/example.slow5")?;
for read in reader.records() {
let read = read?;
Expand Down
8 changes: 5 additions & 3 deletions src/auxiliary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,7 @@ fn parse_aux_field_set_error(ret: i32) -> Slow5Error {
-2 => Slow5Error::MissingAttribute,
-3 => Slow5Error::AuxTypeMismatch,
-4 => Slow5Error::EnumOutOfRange,
_ => unreachable!("Invalid ret: {ret}")

_ => Slow5Error::SetAuxFieldError,
}
}

Expand Down Expand Up @@ -438,7 +437,10 @@ mod test {
assert!(rec.set_aux_field(&mut writer, "char", "a").is_err());

assert!(rec.set_aux_field(&mut writer, "enum", EnumField(1)).is_ok());
assert!(rec.set_aux_field(&mut writer, "enum", EnumField(10)).is_err());
assert!(
rec.set_aux_field(&mut writer, "enum", EnumField(10))
.is_err()
);

Ok(())
}
Expand Down
45 changes: 41 additions & 4 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,31 @@ impl FileReader {
ReadIdIter::new(self)
}

/// Returns iterator over the labels for an enum auxiliary field
/// Returns iterator over the labels for an enum auxiliary field. Useful for
/// converting into an indexable collection
/// and using [`crate::EnumField`] to get the value for an auxiliary field
///
/// # Errors
/// Return Err if field's type is not an auxiliary enum or field is not
/// within in the header
// TODO Example
/// within in the header. This can be due to the wrong name being passed as
/// field, the field is not an enum field or more.
///
/// # Example
/// ```
/// # use slow5::FileReader;
/// # use slow5::EnumField;
/// # fn main() -> anyhow::Result<()> {
/// let mut reader = FileReader::open("examples/example3.blow5")?;
/// let labels = reader
/// .iter_aux_enum_labels("end_reason")?
/// .map(|x| String::from_utf8(x.to_vec()))
/// .collect::<Result<Vec<_>, _>>()?;
/// let rec = reader.get_record("0035aaf9-a746-4bbd-97c4-390ddc27c756")?;
/// let EnumField(idx) = rec.get_aux_field("end_reason")?;
/// assert_eq!(labels[idx], "unknown");
/// # Ok(())
/// # }
/// ```
pub fn iter_aux_enum_labels<B>(&self, field: B) -> Result<AuxEnumLabelIter, Slow5Error>
where
B: Into<Vec<u8>>,
Expand All @@ -205,7 +224,25 @@ impl FileReader {
}

/// Returns iterator over attribute keys for all read groups
// TODO Example
///
/// # Example
/// ```
/// # use slow5::FileReader;
/// # use slow5::EnumField;
/// # use std::collections::HashSet;
/// # fn main() -> anyhow::Result<()> {
/// let mut reader = FileReader::open("examples/example3.blow5")?;
/// let attr_keys = reader
/// .iter_attr_keys()?
/// .map(|attr| std::str::from_utf8(attr).unwrap())
/// .collect::<HashSet<&str>>();
///
/// assert!(attr_keys.contains("file_version"));
/// assert!(attr_keys.contains("asic_id"));
/// assert!(!attr_keys.contains("random attributefdsafs"));
/// # Ok(())
/// # }
/// ```
pub fn iter_attr_keys(&self) -> Result<AttrKeysIter, Slow5Error> {
let mut n = 0;
let keys = unsafe { slow5_get_hdr_keys(self.header().header, &mut n) };
Expand Down
88 changes: 41 additions & 47 deletions src/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,15 @@ impl RecordBuilder {

let read_id_cs = to_cstring(read_id.clone()).map_err(|_| {
libc::free(record as *mut c_void);
BuilderError::ReadIDError})?;
BuilderError::ReadIDError
})?;
let read_id_ptr = read_id_cs.into_raw();
let read_id_len = read_id.len();
(*record).read_id = libc::strdup(read_id_ptr as *const c_char);
(*record).read_id_len = read_id_len
.try_into()
.map_err(|_| {
libc::free(record as *mut c_void);
BuilderError::ConversionError})?;
(*record).read_id_len = read_id_len.try_into().map_err(|_| {
libc::free(record as *mut c_void);
BuilderError::ConversionError
})?;
let _ = CString::from_raw(read_id_ptr);

(*record).read_group = read_group;
Expand All @@ -163,16 +163,14 @@ impl RecordBuilder {
(*record).range = range;
(*record).sampling_rate = sampling_rate;

let len_raw_signal = raw_signal
.len()
.try_into()
.map_err(|_| {
libc::free(record as *mut c_void);
BuilderError::ConversionError})?;
let len_raw_signal = raw_signal.len().try_into().map_err(|_| {
libc::free(record as *mut c_void);
BuilderError::ConversionError
})?;
(*record).len_raw_signal = len_raw_signal;
let raw_signal_ptr = allocate(size_of::<i16>() * raw_signal.len()).map_err(|e| {
libc::free(record as *mut c_void);
e
libc::free(record as *mut c_void);
e
})? as *mut i16;

for (idx, &signal) in raw_signal.iter().enumerate() {
Expand Down Expand Up @@ -212,7 +210,8 @@ impl serde::Serialize for Record {
{
use serde::ser::SerializeMap;
let mut state = serializer.serialize_map(Some(7))?;
let read_id = std::str::from_utf8(self.read_id()).map_err(|_| serde::ser::Error::custom("read_id contains non-UTF8 character"))?;
let read_id = std::str::from_utf8(self.read_id())
.map_err(|_| serde::ser::Error::custom("read_id contains non-UTF8 character"))?;
state.serialize_entry("read_id", read_id)?;
state.serialize_entry("read_group", &self.read_group())?;
state.serialize_entry("digitisation", &self.digitisation())?;
Expand Down Expand Up @@ -625,7 +624,7 @@ mod test {
#[cfg(feature = "serde")]
#[test]
fn test_serialize() -> anyhow::Result<()> {
use serde_test::{Token, assert_ser_tokens};
use serde_test::{assert_ser_tokens, Token};
let rec = RecordBuilder::default()
.read_id("test_id")
.read_group(0)
Expand All @@ -635,37 +634,32 @@ mod test {
.sampling_rate(4000.0)
.raw_signal(&[0, 1, 2, 3])
.build()?;
assert_ser_tokens(&rec, &[
Token::Map { len: Some(7) },

Token::Str("read_id"),
Token::Str("test_id"),

Token::Str("read_group"),
Token::U32(0),

Token::Str("digitisation"),
Token::F64(4096.0),

Token::Str("offset"),
Token::F64(4.0),

Token::Str("range"),
Token::F64(12.0),

Token::Str("sampling_rate"),
Token::F64(4000.0),

Token::Str("raw_signal"),
Token::Seq { len: Some(4) },
Token::I16(0),
Token::I16(1),
Token::I16(2),
Token::I16(3),
Token::SeqEnd,

Token::MapEnd,
]);
assert_ser_tokens(
&rec,
&[
Token::Map { len: Some(7) },
Token::Str("read_id"),
Token::Str("test_id"),
Token::Str("read_group"),
Token::U32(0),
Token::Str("digitisation"),
Token::F64(4096.0),
Token::Str("offset"),
Token::F64(4.0),
Token::Str("range"),
Token::F64(12.0),
Token::Str("sampling_rate"),
Token::F64(4000.0),
Token::Str("raw_signal"),
Token::Seq { len: Some(4) },
Token::I16(0),
Token::I16(1),
Token::I16(2),
Token::I16(3),
Token::SeqEnd,
Token::MapEnd,
],
);
Ok(())
}
}

0 comments on commit a7a0696

Please sign in to comment.