seqtkrs 0.1.1

A Rust reimplementation of seqtk, a fast and lightweight tool for processing biological sequences in FASTA/FASTQ format
Documentation
use crate::core::{SeqReader, SeqRecord, LOOKUP_TABLES};
use anyhow::Result;
use clap::Args;
use rand::Rng;

#[derive(Args, Debug)]
pub struct RandbaseArgs {
    /// 输入FASTA文件
    #[arg(value_name = "in.fa")]
    pub input: String,
}

pub fn run(args: &RandbaseArgs) -> Result<()> {
    let mut reader = if args.input == "-" {
        SeqReader::from_stdin()
    } else {
        SeqReader::from_path(&args.input)?
    };

    let mut record = SeqRecord::new(Vec::new(), Vec::new());
    let mut rng = rand::rng();

    while reader.read_next(&mut record)? {
        print!(">{}", String::from_utf8_lossy(&record.name));

        for (i, &base) in record.seq.iter().enumerate() {
            let c = LOOKUP_TABLES.nt16[base as usize];
            let bitcnt = LOOKUP_TABLES.bitcnt[c as usize];

            let output_base = if bitcnt == 2 {
                let m = rng.random::<bool>();
                let mut selected = 0;
                let mut count = 0;

                for j in 0..4 {
                    if (1 << j) & c != 0 {
                        if count == (m as usize) {
                            selected = j;
                            break;
                        }
                        count += 1;
                    }
                }

                if base.is_ascii_lowercase() {
                    b"acgt"[selected]
                } else {
                    b"ACGT"[selected]
                }
            } else {
                base
            };

            if i % 60 == 0 {
                println!();
            }
            print!("{}", output_base as char);
        }
        println!();
    }

    Ok(())
}