diff --git a/noodles-gff/src/record_buf.rs b/noodles-gff/src/record_buf.rs index 41e16ad30..22f5a8436 100644 --- a/noodles-gff/src/record_buf.rs +++ b/noodles-gff/src/record_buf.rs @@ -2,6 +2,7 @@ pub mod attributes; mod builder; +mod convert; mod field; mod phase; pub mod strand; diff --git a/noodles-gff/src/record_buf/convert.rs b/noodles-gff/src/record_buf/convert.rs new file mode 100644 index 000000000..21805f092 --- /dev/null +++ b/noodles-gff/src/record_buf/convert.rs @@ -0,0 +1,95 @@ +use std::io; + +use super::{attributes::field::Value, RecordBuf, MISSING_FIELD}; +use crate::{record::attributes::field::Value as ValueRef, Record}; + +impl<'l> TryFrom> for RecordBuf { + type Error = io::Error; + + fn try_from(record: Record<'l>) -> Result { + let mut builder = Self::builder(); + + builder = builder + .set_reference_sequence_name(record.reference_sequence_name().into()) + .set_source(record.source().into()) + .set_type(record.ty().into()) + .set_start(record.start()?) + .set_end(record.end()?); + + if record.score() != MISSING_FIELD { + let score = record + .score() + .parse() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + builder = builder.set_score(score); + } + + builder = builder.set_strand(record.strand()?); + + if record.phase() != MISSING_FIELD { + let phase = record + .phase() + .parse() + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + builder = builder.set_phase(phase); + } + + let attributes = record + .attributes() + .iter() + .map(|result| { + result.map(|(k, v)| { + let value = match v { + ValueRef::String(s) => Value::from(s), + ValueRef::Array(values) => { + Value::Array(values.iter().map(String::from).collect()) + } + }; + + (k.into(), value) + }) + }) + .collect::>()?; + + builder = builder.set_attributes(attributes); + + Ok(builder.build()) + } +} + +#[cfg(test)] +mod tests { + use noodles_core::Position; + + use super::*; + use crate::record_buf::Strand; + + #[test] + fn test_try_from_record_for_record_buf() -> Result<(), Box> { + let record = Record::try_new("sq0\t.\texon\t8\t13\t.\t+\t.\tID=0;Name=n0")?; + let actual = RecordBuf::try_from(record)?; + + let expected = RecordBuf::builder() + .set_reference_sequence_name(String::from("sq0")) + .set_source(String::from(".")) + .set_type(String::from("exon")) + .set_start(Position::try_from(8)?) + .set_end(Position::try_from(13)?) + .set_strand(Strand::Forward) + .set_attributes( + [ + (String::from("ID"), Value::from("0")), + (String::from("Name"), Value::from("n0")), + ] + .into_iter() + .collect(), + ) + .build(); + + assert_eq!(actual, expected); + + Ok(()) + } +}