commit - 777c402909372bd380b73ddc0019630a789db099
commit + e1d7e9cc5877f5639f4aa6b411816d62dfa11bc2
blob - 9b4b51299dbdf1b1309cf4c534c3de42f082f2af
blob + 0e03dee51a4d785712069a253a754c01ba65ed4a
--- src/db.rs
+++ src/db.rs
}
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());
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())
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())
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
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..];
blob - 72073007134f750cc2ebde9fb63715792d56dbe0
blob + 31c72cec257e8f0347a67a35a95a4b52f6ed786d
--- src/main.rs
+++ src/main.rs
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)?;
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}"),
);
} 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()))
"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() {