use crate::support::{ByteCodeIter, Run, RLE, RLEIter};
use crate::ENDMARKER;
use crate::support;
use simple_sds::sparse_vector::{SparseVector, SparseBuilder, OneIter};
use simple_sds::ops::{BitVec, Select};
use simple_sds::serialize::Serialize;
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::io::{Error, ErrorKind};
use std::iter::FusedIterator;
use std::ops::Range;
use std::io;
#[cfg(test)]
mod tests;
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Pos {
pub node: usize,
pub offset: usize,
}
impl Pos {
#[inline]
pub fn new(node: usize, offset: usize) -> Self {
Pos {
node, offset,
}
}
}
impl From<(usize, usize)> for Pos {
#[inline]
fn from(pos: (usize, usize)) -> Self {
Self::new(pos.0, pos.1)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BWT {
index: SparseVector,
data: Vec<u8>,
}
impl BWT {
#[inline]
pub fn len(&self) -> usize {
self.index.count_ones()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
fn record_bytes(&self, i: usize) -> &[u8] {
let mut iter = self.index.select_iter(i);
let (_, start) = iter.next().unwrap();
let limit = if i + 1 < self.len() { iter.next().unwrap().1 } else { self.data.len() };
&self.data[start..limit]
}
pub fn record(&self, i: usize) -> Option<Record> {
if i >= self.len() {
return None;
}
let bytes = self.record_bytes(i);
Record::new(i, bytes)
}
pub fn compressed_record(&self, i: usize) -> Option<(&[u8], &[u8])> {
if i >= self.len() {
return None;
}
let bytes = self.record_bytes(i);
let offset = Record::skip_edges(bytes)?;
Some((&bytes[..offset], &bytes[offset..]))
}
pub fn iter(&self) -> RecordIter {
RecordIter {
parent: self,
next: 0,
}
}
pub fn id_iter(&self) -> IdIter {
IdIter {
parent: self,
iter: self.index.one_iter(),
next: 0,
}
}
}
impl Serialize for BWT {
fn serialize_header<T: io::Write>(&self, _: &mut T) -> io::Result<()> {
Ok(())
}
fn serialize_body<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
self.index.serialize(writer)?;
self.data.serialize(writer)?;
Ok(())
}
fn load<T: io::Read>(reader: &mut T) -> io::Result<Self> {
let index = SparseVector::load(reader)?;
let data = Vec::<u8>::load(reader)?;
if index.len() != data.len() {
return Err(Error::new(ErrorKind::InvalidData, "BWT: Index / data length mismatch"));
}
Ok(BWT {
index, data,
})
}
fn size_in_elements(&self) -> usize {
self.index.size_in_elements() + self.data.size_in_elements()
}
}
impl From<BWTBuilder> for BWT {
fn from(source: BWTBuilder) -> Self {
let mut builder = SparseBuilder::new(source.encoder.len(), source.offsets.len()).unwrap();
for offset in source.offsets.iter() {
unsafe { builder.set_unchecked(*offset); }
}
BWT {
index: SparseVector::try_from(builder).unwrap(),
data: Vec::<u8>::from(source.encoder),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct BWTBuilder {
offsets: Vec<usize>,
encoder: RLE,
}
impl BWTBuilder {
pub fn new() -> Self {
BWTBuilder::default()
}
#[inline]
pub fn len(&self) -> usize {
self.offsets.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn append(&mut self, edges: &[Pos], runs: &[Run]) {
self.offsets.push(self.encoder.len());
self.encoder.write_int(edges.len());
let mut prev = 0;
for edge in edges {
self.encoder.write_int(edge.node - prev); self.encoder.write_int(edge.offset);
prev = edge.node;
}
self.encoder.set_sigma(edges.len());
for run in runs {
self.encoder.write(*run);
}
}
}
#[derive(Clone, Debug)]
pub struct RecordIter<'a> {
parent: &'a BWT,
next: usize,
}
impl<'a> Iterator for RecordIter<'a> {
type Item = Record<'a>;
fn next(&mut self) -> Option<Self::Item> {
while self.next < self.parent.len() {
let result = self.parent.record(self.next);
self.next += 1;
if result.is_some() {
return result;
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.parent.len() - self.next))
}
}
impl<'a> FusedIterator for RecordIter<'a> {}
#[derive(Clone, Debug)]
pub struct IdIter<'a> {
parent: &'a BWT,
iter: OneIter<'a>,
next: usize,
}
impl<'a> Iterator for IdIter<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
for (node, offset) in self.iter.by_ref() {
self.next = node + 1;
if self.parent.data[offset] != 0 {
return Some(node);
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.parent.len() - self.next))
}
}
impl<'a> FusedIterator for IdIter<'a> {}
#[derive(Clone, Debug)]
pub struct Record<'a> {
id: usize,
edges: Vec<Pos>,
bwt: &'a [u8],
}
impl<'a> Record<'a> {
pub fn new(id: usize, bytes: &'a [u8]) -> Option<Self> {
if bytes.is_empty() {
return None;
}
let (edges, offset) = Self::decompress_edges(bytes)?;
Some(Record {
id,
edges,
bwt: &bytes[offset..],
})
}
pub unsafe fn from_raw_parts(id: usize, edges: Vec<Pos>, bwt: &'a [u8]) -> Self {
Record { id, edges, bwt }
}
pub fn into_raw_parts(self) -> (usize, Vec<Pos>, &'a [u8]) {
(self.id, self.edges, self.bwt)
}
pub fn decompress_edges(bytes: &[u8]) -> Option<(Vec<Pos>, usize)> {
let mut iter = ByteCodeIter::new(bytes);
let sigma = iter.next().unwrap();
if sigma == 0 {
return None;
}
let mut edges: Vec<Pos> = Vec::new();
let mut prev = 0;
for _ in 0..sigma {
let node = iter.next().unwrap() + prev;
prev = node;
let offset = iter.next().unwrap();
edges.push(Pos::new(node, offset));
}
Some((edges, iter.offset()))
}
fn skip_edges(bytes: &[u8]) -> Option<usize> {
let mut iter = ByteCodeIter::new(bytes);
let sigma = iter.next().unwrap();
if sigma == 0 {
return None;
}
for _ in 0..sigma {
let _ = iter.next().unwrap();
let _ = iter.next().unwrap();
}
Some(iter.offset())
}
pub fn id(&self) -> usize {
self.id
}
#[inline]
pub fn outdegree(&self) -> usize {
self.edges.len()
}
#[inline]
pub fn successor(&self, i: usize) -> usize {
self.edges[i].node
}
#[inline]
pub fn offset(&self, i: usize) -> usize {
self.edges[i].offset
}
pub fn len(&self) -> usize {
let mut result = 0;
for run in RLEIter::with_sigma(self.bwt, self.edges.len()) {
result += run.len;
}
result
}
pub fn is_empty(&self) -> bool {
false
}
pub fn decompress(&self) -> Vec<Pos> {
let mut edges = self.edges.clone();
let mut result: Vec<Pos> = Vec::new();
for run in RLEIter::with_sigma(self.bwt, self.edges.len()) {
for _ in 0..run.len {
result.push(edges[run.value]);
edges[run.value].offset += 1;
}
}
result
}
pub fn lf(&self, i: usize) -> Option<Pos> {
let mut edges = self.edges.clone();
let mut offset = 0;
for run in RLEIter::with_sigma(self.bwt, self.edges.len()) {
if offset + run.len > i {
if self.successor(run.value) == ENDMARKER {
return None;
} else {
edges[run.value].offset += i - offset;
return Some(edges[run.value]);
}
}
edges[run.value].offset += run.len;
offset += run.len;
}
None
}
pub fn predecessor_at(&self, i: usize) -> Option<usize> {
let mut edges: Vec<Pos> = Vec::with_capacity(self.edges.len());
for rank in 0..self.edges.len() {
edges.push(Pos::new(self.successor(rank), 0));
}
for run in RLEIter::with_sigma(self.bwt, self.edges.len()) {
edges[run.value].offset += run.len;
}
for edge in &mut edges {
if edge.node != ENDMARKER {
edge.node = support::flip_node(edge.node);
}
}
for rank in 1..edges.len() {
if support::node_id(edges[rank - 1].node) == support::node_id(edges[rank].node) {
edges.swap(rank - 1, rank);
}
}
let mut offset = 0;
for edge in edges {
offset += edge.offset;
if offset > i {
if edge.node == ENDMARKER {
return None;
}
return Some(edge.node);
}
}
None
}
fn edge_to(&self, node: usize) -> Option<usize> {
let mut low = 0;
let mut high = self.outdegree();
while low < high {
let mid = low + (high - low) / 2;
match node.cmp(&self.edges[mid].node) {
Ordering::Less => high = mid,
Ordering::Equal => return Some(mid),
Ordering::Greater => low = mid + 1,
}
}
None
}
pub fn offset_to(&self, pos: Pos) -> Option<usize> {
if pos.node == ENDMARKER {
return None;
}
let outrank = self.edge_to(pos.node)?;
let mut succ_rank = self.offset(outrank);
if succ_rank > pos.offset {
return None;
}
let mut offset = 0;
for run in RLEIter::with_sigma(self.bwt, self.outdegree()) {
offset += run.len;
if run.value != outrank {
continue;
}
succ_rank += run.len;
if succ_rank > pos.offset {
return Some(offset - (succ_rank - pos.offset));
}
}
None
}
pub fn follow(&self, range: Range<usize>, node: usize) -> Option<Range<usize>> {
if range.is_empty() || node == ENDMARKER {
return None;
}
let rank = self.edge_to(node)?;
let mut result = self.offset(rank)..self.offset(rank);
let mut offset = 0;
for run in RLEIter::with_sigma(self.bwt, self.outdegree()) {
if run.value == rank {
let run_range = offset..offset + run.len;
result.start += support::intersect(&run_range, &(0..range.start)).len();
result.end += support::intersect(&run_range, &(0..range.end)).len();
}
offset += run.len;
if offset >= range.end {
break;
}
}
if result.is_empty() { None } else { Some(result) }
}
pub fn bd_follow(&self, range: Range<usize>, node: usize) -> Option<(Range<usize>, usize)> {
if range.is_empty() || node == ENDMARKER {
return None;
}
let rank = self.edge_to(node)?;
let reverse = support::flip_node(node);
let mut result = self.offset(rank)..self.offset(rank);
let mut count = 0;
let mut offset = 0;
for run in RLEIter::with_sigma(self.bwt, self.outdegree()) {
let run_range = offset..offset + run.len;
if run.value == rank {
result.start += support::intersect(&run_range, &(0..range.start)).len();
result.end += support::intersect(&run_range, &(0..range.end)).len();
}
if support::flip_node(self.successor(run.value)) < reverse {
count += support::intersect(&run_range, &range).len();
}
offset += run.len;
if offset >= range.end {
break;
}
}
if result.is_empty() { None } else { Some((result, count)) }
}
}