use bitnuc_deprec::BitSize;
use rand::{SeedableRng, rngs::SmallRng};
use crate::{Policy, error::Result, policy::RNG_SEED};
#[derive(Clone)]
pub(crate) struct Encoder {
bitsize: BitSize,
sbuffer: Vec<u64>,
xbuffer: Vec<u64>,
s_ibuf: Vec<u8>,
x_ibuf: Vec<u8>,
policy: Policy,
rng: SmallRng,
}
impl Encoder {
pub fn with_policy(bitsize: BitSize, policy: Policy) -> Self {
Self {
bitsize,
policy,
sbuffer: Vec::default(),
xbuffer: Vec::default(),
s_ibuf: Vec::default(),
x_ibuf: Vec::default(),
rng: SmallRng::seed_from_u64(RNG_SEED),
}
}
pub fn policy(&self) -> Policy {
self.policy
}
pub fn encode_single(&mut self, primary: &[u8]) -> Result<Option<&[u64]>> {
self.clear();
if self.bitsize.encode(primary, &mut self.sbuffer).is_err() {
self.clear();
if self
.policy
.handle(primary, &mut self.s_ibuf, &mut self.rng)?
{
self.bitsize.encode(&self.s_ibuf, &mut self.sbuffer)?;
} else {
return Ok(None);
}
}
Ok(Some(&self.sbuffer))
}
pub fn encode_paired(
&mut self,
primary: &[u8],
extended: &[u8],
) -> Result<Option<(&[u64], &[u64])>> {
self.clear();
if self.bitsize.encode(primary, &mut self.sbuffer).is_err()
|| self.bitsize.encode(extended, &mut self.xbuffer).is_err()
{
self.clear();
if self
.policy
.handle(primary, &mut self.s_ibuf, &mut self.rng)?
&& self
.policy
.handle(extended, &mut self.x_ibuf, &mut self.rng)?
{
self.bitsize.encode(&self.s_ibuf, &mut self.sbuffer)?;
self.bitsize.encode(&self.x_ibuf, &mut self.xbuffer)?;
} else {
return Ok(None);
}
}
Ok(Some((&self.sbuffer, &self.xbuffer)))
}
pub fn clear(&mut self) {
self.sbuffer.clear();
self.xbuffer.clear();
self.s_ibuf.clear();
self.x_ibuf.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_single_invalid_ignored() {
let mut encoder = Encoder::with_policy(BitSize::Two, Policy::IgnoreSequence);
assert!(encoder.encode_single(b"ACGTNNNN").unwrap().is_none());
}
#[test]
fn test_encode_single_invalid_corrected() {
let mut encoder = Encoder::with_policy(BitSize::Two, Policy::SetToA);
assert!(encoder.encode_single(b"ACGTNNNN").unwrap().is_some());
}
#[test]
fn test_encode_paired_invalid_ignored() {
let mut encoder = Encoder::with_policy(BitSize::Two, Policy::IgnoreSequence);
assert!(
encoder
.encode_paired(b"ACGTNNNN", b"ACGTACGT")
.unwrap()
.is_none()
);
}
#[test]
fn test_encode_paired_invalid_corrected() {
let mut encoder = Encoder::with_policy(BitSize::Two, Policy::SetToA);
assert!(
encoder
.encode_paired(b"ACGTNNNN", b"NNNNACGT")
.unwrap()
.is_some()
);
}
}