⬆️ refactor superkmer to use obipipeline
- Replace manual threading with Pipeline abstraction from `obipipline` - Remove crossbeam-channel dependency and format detection logic - Introduce typed `PipelineData` enum for pipeline stages (RawChunk, Norm Chunk, Batch) - Implement shared normalization and extraction steps as `SharedFn`ƒ - Add unsafe Send/Sync impls for PipelineData (Rope ownership is moved, not shared) - Replace manual reader/worker/output threads with a single Pipeline execution - Uses `make_source_fallible!`, shared transform functions, and a sink for output - Simplify argument handling (remove `--format` flag) - Update Cargo.toml: remove crossbeam-channel, add obipipeline
This commit is contained in:
@@ -194,7 +194,10 @@ pub trait RopeCursor<'a> {
|
||||
/// Use the returned value with [`SeekMode::Rope`] to restore a position,
|
||||
/// or as a truncation point after a write pass.
|
||||
fn rope_tell(&self) -> usize {
|
||||
self.state().current.get().unwrap_or(self.state().offset.get())
|
||||
self.state()
|
||||
.current
|
||||
.get()
|
||||
.unwrap_or(self.state().offset.get())
|
||||
}
|
||||
|
||||
/// Number of bytes visible through this cursor (`rope.len() - offset`).
|
||||
@@ -528,13 +531,13 @@ mod tests {
|
||||
use crate::Rope;
|
||||
|
||||
fn rope(data: &[u8]) -> Rope {
|
||||
let mut r = Rope::new();
|
||||
let mut r = Rope::new(None);
|
||||
r.push(data.to_vec());
|
||||
r
|
||||
}
|
||||
|
||||
fn rope2(a: &[u8], b: &[u8]) -> Rope {
|
||||
let mut r = Rope::new();
|
||||
let mut r = Rope::new(None);
|
||||
r.push(a.to_vec());
|
||||
r.push(b.to_vec());
|
||||
r
|
||||
@@ -703,14 +706,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn backward_empty_rope_returns_error() {
|
||||
let r = Rope::new();
|
||||
let r = Rope::new(None);
|
||||
let c = r.bw_cursor();
|
||||
assert!(c.read_next().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn forward_empty_rope_returns_error() {
|
||||
let r = Rope::new();
|
||||
let r = Rope::new(None);
|
||||
let c = r.fw_cursor();
|
||||
assert!(c.read_next().is_err());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ use std::cell::Cell;
|
||||
///
|
||||
/// See the [module-level documentation][crate::rope] for a full overview.
|
||||
pub struct Rope {
|
||||
pub(crate) mime_type: Option<&'static str>,
|
||||
pub(crate) blocks: Vec<Vec<Cell<u8>>>,
|
||||
pub(crate) length: usize,
|
||||
pub(crate) start_block_idx: Vec<usize>,
|
||||
@@ -35,8 +36,9 @@ pub struct Rope {
|
||||
|
||||
impl Rope {
|
||||
/// Create an empty rope (no allocations).
|
||||
pub fn new() -> Self {
|
||||
pub fn new(mime_type: Option<&'static str>) -> Self {
|
||||
Self {
|
||||
mime_type,
|
||||
blocks: Vec::new(),
|
||||
length: 0,
|
||||
start_block_idx: Vec::new(),
|
||||
@@ -59,6 +61,11 @@ impl Rope {
|
||||
self.length += block_len;
|
||||
}
|
||||
|
||||
/// The MIME type of the rope, if known.
|
||||
pub fn mime_type(&self) -> Option<&str> {
|
||||
self.mime_type.as_deref()
|
||||
}
|
||||
|
||||
/// Total number of blocks.
|
||||
pub fn n_blocks(&self) -> usize {
|
||||
self.blocks.len()
|
||||
@@ -115,7 +122,7 @@ impl Rope {
|
||||
}
|
||||
|
||||
if pos == self.length {
|
||||
return Ok(Rope::new());
|
||||
return Ok(Rope::new(self.mime_type.clone()));
|
||||
}
|
||||
|
||||
let (block_idx, from, _) = self.lookup(pos).ok_or_else(|| {
|
||||
@@ -149,6 +156,7 @@ impl Rope {
|
||||
self.length = pos;
|
||||
|
||||
Ok(Rope {
|
||||
mime_type: self.mime_type.clone(),
|
||||
blocks: tail_blocks,
|
||||
length: tail_length,
|
||||
start_block_idx: tail_starts,
|
||||
@@ -185,13 +193,13 @@ mod tests {
|
||||
}
|
||||
|
||||
fn make(data: &[u8]) -> Rope {
|
||||
let mut r = Rope::new();
|
||||
let mut r = Rope::new(None);
|
||||
r.push(data.to_vec());
|
||||
r
|
||||
}
|
||||
|
||||
fn make2(a: &[u8], b: &[u8]) -> Rope {
|
||||
let mut r = Rope::new();
|
||||
let mut r = Rope::new(None);
|
||||
r.push(a.to_vec());
|
||||
r.push(b.to_vec());
|
||||
r
|
||||
@@ -201,7 +209,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn empty_rope_is_empty() {
|
||||
let r = Rope::new();
|
||||
let r = Rope::new(None);
|
||||
assert!(r.is_empty());
|
||||
assert_eq!(r.len(), 0);
|
||||
assert_eq!(r.n_blocks(), 0);
|
||||
@@ -213,6 +221,7 @@ mod tests {
|
||||
assert!(!r.is_empty());
|
||||
assert_eq!(r.len(), 5);
|
||||
assert_eq!(r.n_blocks(), 1);
|
||||
assert_eq!(r.mime_type(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -220,6 +229,7 @@ mod tests {
|
||||
let r = make2(b"abc", b"de");
|
||||
assert_eq!(r.len(), 5);
|
||||
assert_eq!(r.n_blocks(), 2);
|
||||
assert_eq!(r.mime_type(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -261,7 +271,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn lookup_empty_rope_returns_none() {
|
||||
assert!(Rope::new().lookup(0).is_none());
|
||||
assert!(Rope::new(None).lookup(0).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user