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:
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() {