virittaa

Log | Files | Refs | README | LICENSE

commit e1d7e9cc5877f5639f4aa6b411816d62dfa11bc2
parent 777c402909372bd380b73ddc0019630a789db099
Author: mtmn <miro@haravara.org>
Date:   Thu, 14 May 2026 12:58:39 +0200

fix: respect `--limit` on each argument

Diffstat:
Msrc/db.rs | 33+++++++++++++++++++++++++--------
Msrc/main.rs | 11+++++------
2 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/src/db.rs b/src/db.rs @@ -40,7 +40,7 @@ pub struct LibraryDb { } const SEP: u8 = 0x00; -const BPM_KEY_LEN: usize = 8; +const BPM_KEY_LEN: usize = 8; // f64 big-endian fn prefix_index_key(value: &[u8], primary_key: &[u8]) -> Vec<u8> { let mut buf = Vec::with_capacity(value.len() + 1 + primary_key.len()); @@ -223,16 +223,19 @@ impl LibraryDb { Ok(results) } - /// Find tracks by artist name prefix (case-insensitive). + /// Find tracks by artist name prefix (case-insensitive), up to `limit` items. /// /// # Errors /// /// Returns an error if the index scan or deserialization fails. - pub fn find_by_artist(&self, prefix: &str) -> Result<Vec<(String, TrackReport)>> { + pub fn find_by_artist(&self, prefix: &str, limit: usize) -> Result<Vec<(String, TrackReport)>> { let prefix_lower = prefix.to_lowercase(); let mut results = Vec::new(); for item in self.artist_tree.scan_prefix(prefix_lower.as_bytes()) { + if results.len() >= limit { + break; + } let (idx_key, _) = item.context("Failed to read artist index")?; let primary_key_bytes = extract_primary_key(&idx_key)?; let primary_key = String::from_utf8(primary_key_bytes.to_vec()) @@ -246,16 +249,19 @@ impl LibraryDb { Ok(results) } - /// Find tracks by key signature prefix (case-insensitive). + /// Find tracks by key signature prefix (case-insensitive), up to `limit` items. /// /// # Errors /// /// Returns an error if the index scan or deserialization fails. - pub fn find_by_key(&self, prefix: &str) -> Result<Vec<(String, TrackReport)>> { + pub fn find_by_key(&self, prefix: &str, limit: usize) -> Result<Vec<(String, TrackReport)>> { let prefix_lower = prefix.to_lowercase(); let mut results = Vec::new(); for item in self.key_tree.scan_prefix(prefix_lower.as_bytes()) { + if results.len() >= limit { + break; + } let (idx_key, _) = item.context("Failed to read key index")?; let primary_key_bytes = extract_primary_key(&idx_key)?; let primary_key = String::from_utf8(primary_key_bytes.to_vec()) @@ -269,12 +275,17 @@ impl LibraryDb { Ok(results) } - /// Find tracks with BPM in the given range (inclusive). + /// Find tracks with BPM in the given range (inclusive), up to `limit` items. /// /// # Errors /// /// Returns an error if the index scan or deserialization fails. - pub fn find_by_bpm_range(&self, min: f64, max: f64) -> Result<Vec<(String, TrackReport)>> { + pub fn find_by_bpm_range( + &self, + min: f64, + max: f64, + limit: usize, + ) -> Result<Vec<(String, TrackReport)>> { let mut results = Vec::new(); // Sled sorts longer keys after their prefix, so a bare 8-byte bound would @@ -283,7 +294,13 @@ impl LibraryDb { upper.extend_from_slice(&max.to_be_bytes()); upper.push(0xFF); - for item in self.bpm_tree.range(min.to_be_bytes().as_slice()..upper.as_slice()) { + for item in self + .bpm_tree + .range(min.to_be_bytes().as_slice()..upper.as_slice()) + { + if results.len() >= limit { + break; + } let (idx_key, _) = item.context("Failed to read bpm index")?; // Primary key starts after 8-byte BPM + 1-byte separator. let primary_key_bytes = &idx_key[BPM_KEY_LEN + 1..]; diff --git a/src/main.rs b/src/main.rs @@ -156,6 +156,7 @@ fn main() -> Result<()> { if is_db_query { let db = LibraryDb::open(std::path::Path::new(&db_path))?; + let effective_limit = if limit == 0 { usize::MAX } else { limit }; if let Some(mixxx_path) = import_mixxx_path { let count = import_mixxx(&db, mixxx_path)?; @@ -169,21 +170,21 @@ fn main() -> Result<()> { None => eprintln!("No track found for key: {query_key}"), } } else if let Some(prefix) = artist_prefix { - let entries = db.find_by_artist(prefix)?; + let entries = db.find_by_artist(prefix, effective_limit)?; print_entries( &entries, &format!("No tracks found for artist prefix: {prefix}"), "track(s) found.", ); } else if let Some(prefix) = key_prefix { - let entries = db.find_by_key(prefix)?; + let entries = db.find_by_key(prefix, effective_limit)?; print_entries( &entries, &format!("No tracks found for key prefix: {prefix}"), "track(s) found.", ); } else if let Some((min, max)) = bpm_range { - let entries = db.find_by_bpm_range(min, max)?; + let entries = db.find_by_bpm_range(min, max, effective_limit)?; print_entries( &entries, &format!("No tracks found with BPM between {min} and {max}"), @@ -191,8 +192,7 @@ fn main() -> Result<()> { ); } else if let Some(pattern) = search_pattern { let re = Regex::new(pattern)?; - let list_limit = if limit == 0 { usize::MAX } else { limit }; - let entries = db.list(list_limit)?; + let entries = db.list(effective_limit)?; let matches_found: Vec<_> = entries .into_iter() .filter(|(key, report)| re.is_match(key) || re.is_match(&report.to_string())) @@ -203,7 +203,6 @@ fn main() -> Result<()> { "match(es) found.", ); } else { - let effective_limit = if limit == 0 { usize::MAX } else { limit }; let entries = db.list(effective_limit)?; let total = db.count()?; if entries.is_empty() {