primer3 0.1.0

Safe Rust bindings to the primer3 primer design library
Documentation
// Pedantic lint overrides for FFI-heavy crate:
// - Casting between c_int/usize is inherent to FFI bridging code
// - Many small builder/getter methods don't benefit from #[must_use]
#![allow(
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_sign_loss,
    clippy::must_use_candidate,
    clippy::return_self_not_must_use
)]

//! # primer3
//!
//! Safe, idiomatic Rust bindings to the [primer3](https://primer3.org/) C library
//! for PCR primer design and oligonucleotide thermodynamic calculations.
//!
//! ## Quick Start
//!
//! ### Melting Temperature
//!
//! ```no_run
//! use primer3::calc_tm;
//!
//! let tm = calc_tm("GTAAAACGACGGCCAGT").unwrap();
//! println!("Tm = {tm:.1}°C");
//! ```
//!
//! ### Thermodynamic Analysis
//!
//! ```no_run
//! use primer3::{calc_hairpin, calc_homodimer, calc_heterodimer};
//!
//! let hairpin = calc_hairpin("CCCCCATCCGATCAGGGGG").unwrap();
//! println!("Hairpin Tm = {:.1}°C, dG = {:.0} cal/mol", hairpin.tm(), hairpin.dg());
//!
//! let dimer = calc_heterodimer("AAAAAAAAAA", "TTTTTTTTTT").unwrap();
//! println!("Heterodimer Tm = {:.1}°C", dimer.tm());
//! ```
//!
//! ### Primer Design
//!
//! ```no_run
//! use primer3::{design_primers, SequenceArgs, PrimerSettings};
//!
//! let seq_args = SequenceArgs::builder()
//!     .sequence("ATCGATCG...")
//!     .target(100, 200)  // start=100, length=200
//!     .build()
//!     .unwrap();
//!
//! let settings = PrimerSettings::builder()
//!     .primer_opt_tm(60.0)
//!     .primer_min_tm(57.0)
//!     .primer_max_tm(63.0)
//!     .product_size_range(75, 150)
//!     .build()
//!     .unwrap();
//!
//! let result = design_primers(&seq_args, &settings, None, None).unwrap();
//! for pair in result.pairs() {
//!     println!("{}", pair.left().sequence());
//! }
//! ```
//!
//! ## Thread Safety
//!
//! The underlying C library uses global state for thermodynamic parameters,
//! which are compiled in from `thal_default_params.h` (no file I/O needed).
//! Thermodynamic calculation functions (`calc_tm`, `calc_hairpin`, etc.) are
//! safe to call concurrently. Both `design_primers()` and `align()` are
//! mutex-guarded because the underlying C routines use mutable global state
//! (primer3's internal bookkeeping and dpal's ~40 MB scoring/traceback
//! matrices, respectively).
//!
//! ## Defaults
//!
//! This crate uses primer3 C library v2 defaults (`p3_create_global_settings()`).
//! Some defaults differ from primer3-py -- consult the primer3 manual for details.

mod alignment;
pub mod boulder;
mod conditions;
mod design;
mod error;
mod init;
mod results;
mod seq_lib;
mod sequence;
mod settings;
mod thermo;
mod tm;
mod utils;
mod weights;

pub use alignment::{
    AlignmentArgs, AlignmentMode, AlignmentOutput, AlignmentResult, MAX_ALIGN_LENGTH, align,
};
pub use conditions::SolutionConditions;
pub use design::design_primers;
pub use error::{Primer3Error, Result};
pub use results::{DesignResult, OligoType, PrimerPair, PrimerRecord};
pub use seq_lib::SequenceLibrary;
pub use sequence::{Interval, OkRegionPair, SequenceArgs, SequenceArgsBuilder};
pub use settings::{OligoSettings, PrimerSettings, PrimerSettingsBuilder, PrimerTask};
pub use thermo::{
    ThermoArgs, ThermoResult, calc_end_stability, calc_end_stability_with, calc_hairpin,
    calc_hairpin_with, calc_heterodimer, calc_heterodimer_with, calc_homodimer,
    calc_homodimer_with,
};
pub use tm::{
    SaltCorrectionMethod, TmMethod, TmParams, calc_end_oligodg, calc_end_oligodg_with,
    calc_oligodg, calc_oligodg_with, calc_tm, calc_tm_with,
};
pub use utils::{divalent_to_monovalent, is_symmetric, reverse_complement};
pub use weights::{OligoWeights, PairWeights};