Skip to main content

sshash_lib/
lib.rs

1// SSHash: Sparse and Skew Hashing of k-mers
2//
3// A Rust implementation of the SSHash compressed k-mer dictionary,
4// providing efficient storage and querying of k-mer sets.
5
6#![doc = include_str!("../README.md")]
7#![warn(missing_docs)]
8
9pub mod constants;
10pub mod encoding;
11pub mod hasher;
12pub mod kmer;
13pub mod minimizer;
14pub mod mphf_config;
15pub mod offsets;
16pub mod minimizers_control_map;
17pub mod spectrum_preserving_string_set;
18pub mod partitioned_mphf;
19pub mod sparse_and_skew_index;
20pub mod streaming_query;
21pub mod dictionary;
22pub mod builder;
23pub mod serialization;
24pub mod kmer_dict_trait;
25
26// Re-export common types at crate root 
27pub use kmer::{Kmer, Kmer21, Kmer31, Kmer63, KmerBits};
28pub use minimizer::{MinimizerInfo, MinimizerIterator};
29pub use minimizers_control_map::{MinimizersControlMap, MinimizersControlMapBuilder, BucketType};
30pub use streaming_query::{LookupResult, StreamingQuery};
31pub use dictionary::Dictionary;
32pub use kmer_dict_trait::{KmerDictionary, KmerStreamingQuery};
33pub use builder::{BuildConfiguration, CfSegData, DictionaryBuilder, parse_cf_seg};
34pub use partitioned_mphf::PartitionedMphf;
35
36/// Dispatch to the correct const generic `K` based on a runtime `k` value.
37///
38/// The const generic `K` determines both the storage type (`u64` for K ≤ 31,
39/// `u128` for K > 31) **and** the k-mer length used in operations like
40/// `reverse_complement()`, `from_str()`, and `decode_kmer()`.  Therefore `K`
41/// must always equal the actual k value, not merely the maximum for the
42/// storage class.
43///
44/// `k` must be an odd value in \[3, 63\]; these are the only values for which
45/// [`KmerBits`] is implemented.
46///
47/// # Usage
48///
49/// ```ignore
50/// use sshash_lib::dispatch_on_k;
51///
52/// dispatch_on_k!(k, K => {
53///     let kmer = Kmer::<K>::from_string(s)?;
54///     dict.lookup::<K>(&kmer)
55/// })
56/// ```
57///
58/// # Panics
59///
60/// Panics at runtime if `k` is even or outside the \[3, 63\] range.
61#[macro_export]
62macro_rules! dispatch_on_k {
63    ($k:expr, $K:ident => $body:expr) => {{
64        match $k {
65            3  => { const $K: usize = 3;  $body }
66            5  => { const $K: usize = 5;  $body }
67            7  => { const $K: usize = 7;  $body }
68            9  => { const $K: usize = 9;  $body }
69            11 => { const $K: usize = 11; $body }
70            13 => { const $K: usize = 13; $body }
71            15 => { const $K: usize = 15; $body }
72            17 => { const $K: usize = 17; $body }
73            19 => { const $K: usize = 19; $body }
74            21 => { const $K: usize = 21; $body }
75            23 => { const $K: usize = 23; $body }
76            25 => { const $K: usize = 25; $body }
77            27 => { const $K: usize = 27; $body }
78            29 => { const $K: usize = 29; $body }
79            31 => { const $K: usize = 31; $body }
80            33 => { const $K: usize = 33; $body }
81            35 => { const $K: usize = 35; $body }
82            37 => { const $K: usize = 37; $body }
83            39 => { const $K: usize = 39; $body }
84            41 => { const $K: usize = 41; $body }
85            43 => { const $K: usize = 43; $body }
86            45 => { const $K: usize = 45; $body }
87            47 => { const $K: usize = 47; $body }
88            49 => { const $K: usize = 49; $body }
89            51 => { const $K: usize = 51; $body }
90            53 => { const $K: usize = 53; $body }
91            55 => { const $K: usize = 55; $body }
92            57 => { const $K: usize = 57; $body }
93            59 => { const $K: usize = 59; $body }
94            61 => { const $K: usize = 61; $body }
95            63 => { const $K: usize = 63; $body }
96            other => panic!(
97                "Unsupported k value: {}. k must be an odd value between 3 and 63.",
98                other,
99            ),
100        }
101    }};
102}
103
104/// Version information
105pub fn version() -> (u8, u8, u8) {
106    constants::VERSION
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn test_version() {
115        let (major, minor, patch) = version();
116        assert_eq!(major, 0);
117        assert_eq!(minor, 1);
118        assert_eq!(patch, 0);
119    }
120}