diff --git a/microBioRust/src/embl.rs b/microBioRust/src/embl.rs index b38df7d..07c1fbe 100644 --- a/microBioRust/src/embl.rs +++ b/microBioRust/src/embl.rs @@ -747,24 +747,7 @@ where } } -///stores a value for start or stop (end) which can be denoted as a < value or > value. -#[derive(Debug, Hash, PartialEq, Eq, Clone)] -pub enum RangeValue { - Exact(u32), - LessThan(u32), - GreaterThan(u32), -} - -//trait for rangevalue -impl RangeValue { - pub fn get_value(&self) -> u32 { - match self { - RangeValue::Exact(value) => *value, - RangeValue::LessThan(value) => *value, - RangeValue::GreaterThan(value) => *value, - } - } -} +pub use crate::record::RangeValue; ///stores the details of the source features in genbank (contigs) #[derive(Debug, Eq, PartialEq, Hash, Clone)] @@ -1379,6 +1362,25 @@ impl Default for Record { } } +// Provide a type alias and conversion to a generic record to aid interoperability +pub type GenericRecordEmbl = crate::record::GenericRecord; + +impl From<&Record> for GenericRecordEmbl { + fn from(r: &Record) -> Self { + Self { + id: r.id.clone(), + seq: r.sequence.clone(), + seqid: r.id.clone(), + start: r.start as u32, + end: r.end as u32, + strand: r.strand, + source: r.source_map.clone(), + cds: r.cds.clone(), + seq_features: r.seq_features.clone(), + } + } +} + #[allow(dead_code)] pub struct Config { filename: String, diff --git a/microBioRust/src/gbk.rs b/microBioRust/src/gbk.rs index 652e7fe..5bae988 100644 --- a/microBioRust/src/gbk.rs +++ b/microBioRust/src/gbk.rs @@ -363,7 +363,7 @@ macro_rules! create_builder { self.$attributes } // function to iterate immutably through the BTreeMap as required - pub fn iter_sorted(&self) -> std::collections::btree_map::Iter> { + pub fn iter_sorted(&'_ self) -> std::collections::btree_map::Iter> { self.$attributes.iter() } //default function @@ -816,24 +816,7 @@ where } } -///stores a value for start or stop (end) which can be denoted as a < value or > value. -#[derive(Debug, Hash, PartialEq, Eq, Clone)] -pub enum RangeValue { - Exact(u32), - LessThan(u32), - GreaterThan(u32), -} - -//trait for rangevalue -impl RangeValue { - pub fn get_value(&self) -> u32 { - match self { - RangeValue::Exact(value) => *value, - RangeValue::LessThan(value) => *value, - RangeValue::GreaterThan(value) => *value, - } - } -} +pub use crate::record::RangeValue; //stores the details of the source features in genbank (contigs) #[derive(Debug, Eq, PartialEq, Hash, Clone)] @@ -1549,6 +1532,25 @@ impl Default for Record { } } +// Provide a type alias and conversion to a generic record to aid interoperability +pub type GenericRecordGbk = crate::record::GenericRecord; + +impl From<&Record> for GenericRecordGbk { + fn from(r: &Record) -> Self { + Self { + id: r.id.clone(), + seq: r.sequence.clone(), + seqid: r.id.clone(), + start: r.start as u32, + end: r.end as u32, + strand: r.strand, + source: r.source_map.clone(), + cds: r.cds.clone(), + seq_features: r.seq_features.clone(), + } + } +} + #[allow(dead_code)] pub struct Config { filename: String, diff --git a/microBioRust/src/lib.rs b/microBioRust/src/lib.rs index 31eace6..3c60d8e 100644 --- a/microBioRust/src/lib.rs +++ b/microBioRust/src/lib.rs @@ -9,5 +9,6 @@ //! Additionally, you can create new features and records and save them either in genbank or gff3 format //! #![allow(non_snake_case)] +pub mod record; pub mod embl; pub mod gbk; diff --git a/microBioRust/src/record.rs b/microBioRust/src/record.rs new file mode 100644 index 0000000..27d34be --- /dev/null +++ b/microBioRust/src/record.rs @@ -0,0 +1,74 @@ +///Shared generic record types to reduce duplication between gbk and embl +///Minimal initial introduction: defines generic containers and builders that mirror the existing API where possible + +use std::collections::{HashMap, HashSet}; + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum RangeValue { + Exact(u32), + LessThan(u32), + GreaterThan(u32), +} + +impl RangeValue { + pub fn get_value(&self) -> u32 { + match self { + RangeValue::Exact(v) => *v, + RangeValue::LessThan(v) => *v, + RangeValue::GreaterThan(v) => *v, + } + } +} + +///Traits to unify attribute enums across formats. Existing enums can implement Into these trait views if needed +pub trait HasStartStopStrand { + fn start(&self) -> Option { None } + fn stop(&self) -> Option { None } + fn strand(&self) -> Option { None } +} + +///Generic attribute builders +#[derive(Clone, Debug, Default)] +pub struct AttributeBuilder { + pub name: Option, + pub attributes: HashMap>, +} + +impl AttributeBuilder +where + K: Eq + std::hash::Hash, + V: Eq + std::hash::Hash, +{ + pub fn set_name(&mut self, name: String) { self.name = Some(name); } + pub fn get_name(&self) -> Option<&String> { self.name.as_ref() } + pub fn add(&mut self, key: K, value: V) { + self.attributes.entry(key).or_insert_with(HashSet::new).insert(value); + } + pub fn get(&self, key: &K) -> Option<&HashSet> { self.attributes.get(key) } +} + +///Generic record and records container +#[derive(Clone, Debug, Default)] +pub struct GenericRecord { + pub id: String, + pub seq: String, + pub seqid: String, + pub start: u32, + pub end: u32, + pub strand: i32, + pub source: S, + pub cds: F, + pub seq_features: Q, +} + +impl GenericRecord { + pub fn is_empty(&self) -> bool { self.id.is_empty() && self.seq.is_empty() } +} + +pub struct GenericRecords { + inner: R, +} + +impl GenericRecords { + pub fn new(reader: R) -> Self { Self { inner: reader } } +}