twitcher 0.1.8

Find template switch mutations in genomic data
use bitvec::vec::BitVec;
use rust_htslib::bcf;

use crate::common::{SequencePair, aligner::InProgress, coords::GenomePosition};

#[derive(Debug)]
pub(super) struct Cluster {
    // TODO what if a record has multiple ALT alleles?
    pub mask: BitVec,
}

impl Cluster {
    pub(super) fn new(record_bitmask: BitVec) -> Self {
        Self {
            mask: record_bitmask,
        }
    }

    pub fn apply_to_records<'m, 'r>(&'m self, records: &'r [bcf::Record]) -> MaskedRecords<'r, 'm> {
        MaskedRecords {
            records,
            cluster: self,
        }
    }
}

pub type ListOfClusters = Vec<(Cluster, GenomePosition, SequencePair, InProgress)>;

pub(super) struct Message {
    pub orig_records: Vec<bcf::Record>,
    pub clusters: ListOfClusters,
}

impl Message {
    pub(super) fn passthrough(orig_records: Vec<bcf::Record>) -> Self {
        Self {
            orig_records,
            clusters: Vec::new(),
        }
    }

    pub(super) fn cluster(orig_records: Vec<bcf::Record>, clusters: ListOfClusters) -> Self {
        Self {
            orig_records,
            clusters,
        }
    }

    pub(super) fn is_passthrough(&self) -> bool {
        self.clusters.is_empty()
    }
}

#[derive(Clone, Copy)]
pub struct MaskedRecords<'r, 'c> {
    records: &'r [bcf::Record],
    cluster: &'c Cluster,
}

impl<'r> MaskedRecords<'r, '_> {
    pub fn masked_iter(&self) -> impl Iterator<Item = &'r bcf::Record> {
        self.cluster
            .mask
            .iter_ones()
            .map(move |ix| &self.records[ix])
    }

    pub fn masked_len(&self) -> usize {
        self.cluster.mask.count_ones()
    }

    #[expect(unused)]
    pub fn unmasked_len(&self) -> usize {
        self.records.len()
    }
}