Skip to content
This repository has been archived by the owner on Nov 28, 2024. It is now read-only.

Showcase Generic Actions via Demo #11

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions samples/well_formed_sample.bed
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
chr7 127471196 127472363
chr7 127472363 127473530
chr7 127473530 127474697
52 changes: 1 addition & 51 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1 @@
pub mod error;

//use async_trait::async_trait;
use serde::{Serializer, ser::SerializeStruct};
//use serde::{Deserializer, ser::DeserializeStruct};
//use error::BioSerdeError;
//use arrow::record_batch::{RecordBatchReader};

// TODO: This should ideally be moved to a specific module (crate?) encapsulating
// all traditional bioinformatics formats and its associated (util) methods.
// use noodles::bam::AsyncReader as BamReader;
// use noodles::bcf::AsyncReader as BcfReader;
//use noodles::bed::Reader as BedReader;
use noodles::bed::Writer as BedWriter;
// use noodles::cram::AsyncReader as CramReader;
// use noodles::fasta::AsyncReader as FastaReader;
// use noodles::fastq::AsyncReader as FastqReader;
// use noodles::vcf::AsyncReader as VcfReader;

// Refer to https://serde.rs/custom-serialization.html for details on
// Custom Serialization.
pub trait Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer;
}
struct ModernBioFormat<F> {
writer: F,
destination: String,
}

impl Serialize for ModernBioFormat<F: BedWriter> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut bio = serializer.serialize_struct("ModernBioFormat", 2)?;
bio.serialize_field("format", &self.format)?;
bio.serialize_field("destination", &self.destination)?;
bio.end()
}
}

// impl Deserialize for TraditionalBioFormat {
// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
// where
// D: Deserializer,
// {
// deserializer.deserialize_struct("Color", &["r", "g", "b"], ColorVisitor)
// }
// }
pub mod error;
78 changes: 76 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,77 @@
fn main() {
println!("Hello, world!");
use noodles_bed as bed;
use std::{env, error::Error, fs, path::Path, sync::Arc, io::{Read, Write}};


// // This is what it seems like we should do
// struct ModernBioFormat<F1: BioSerdeRead, F2: BioSerdeWrite> {
// reader: F1,
// writer: F2,
// origin: String,
// destination: String,
// }

// // How to represent "Bed" here?
// // we may even have an enum of ImplementedFormats
// impl BioSerdeRead for Bed {...}
// impl BioSerdeWrite for Bed {...}

// This experiment doesn't work:
// we would need a generic trait that says
// that says that there Writers and Readers are already taken care of
// by our code
struct ModernBioFormat<F1: Read, F2: Write> {
reader: F1,
writer: F2,
origin: String,
destination: String,
}

pub fn run<F1: Read, F2: Write>(mbf: ModernBioFormat<F1, F2>) -> Result<(), Box<dyn Error>> {
let bed_records_vec = mbf
.reader
// This is a specific Bed Reading mechanism
// that is bleeding in a generic part of the code
.records::<3>()
.filter_map(|record| record.ok())
.collect();

for record in bed_records_vec.iter() {
// This points out a problem:
// even if we solve generic writers and readers
// the bulk of our work will be to make the <write_record> itself
//
// In the specific case of Bed, it asks for specifically a bed::Record type.
// which is a problem, because it forces our hand to conform
// to a specific implementation
// whereas being able to receive a generic trait of some sorts
// would enable us to pass the IR main struct directly
// (maybe we can already rehearse making a noodles PR in that sense
// but that would require us to already have the IR definition)
mbf.writer.write_record::<3>(&record)?;
}

Ok(())
}

fn main() {
let input_file = "samples/well_formed_sample.bed".to_string();
let output_file = "output.bed".to_string();

let data = fs::read(&mbf.origin)?;
let mut reader = bed::Reader::new(&data[..]);

let path = Path::new(&destination);
let file = fs::File::create(&path)?;
let mut writer = bed::Writer::new(file);

let mbf = ModernBioFormat {
reader,
writer,
origin: input_file,
destination: output_file,
};

// identity test. read and write the same bed.
run(mbf);

}