Store search index fields in array

This commit is contained in:
Antoine Gersant 2024-09-23 20:35:16 -07:00
parent ee3f9fd5a0
commit 971b46be45
4 changed files with 46 additions and 61 deletions

22
Cargo.lock generated
View file

@ -631,6 +631,27 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "enum-map"
version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
dependencies = [
"enum-map-derive",
"serde",
]
[[package]]
name = "enum-map-derive"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -1669,6 +1690,7 @@ dependencies = [
"chumsky", "chumsky",
"daemonize", "daemonize",
"embed-resource", "embed-resource",
"enum-map",
"getopts", "getopts",
"headers", "headers",
"http 1.1.0", "http 1.1.0",

View file

@ -16,6 +16,7 @@ base64 = "0.22.1"
bitcode = { version = "0.6.3", features = ["serde"] } bitcode = { version = "0.6.3", features = ["serde"] }
branca = "0.10.1" branca = "0.10.1"
chumsky = "0.9.3" chumsky = "0.9.3"
enum-map = { version = "2.7.3", features = ["serde"] }
getopts = "0.2.21" getopts = "0.2.21"
headers = "0.4" headers = "0.4"
http = "1.1.0" http = "1.1.0"

View file

@ -6,9 +6,10 @@ use chumsky::{
text::{int, keyword, whitespace, TextParser}, text::{int, keyword, whitespace, TextParser},
Parser, Parser,
}; };
use enum_map::Enum;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Enum, Eq, Hash, PartialEq, Serialize)]
pub enum TextField { pub enum TextField {
Album, Album,
AlbumArtist, AlbumArtist,
@ -27,7 +28,7 @@ pub enum TextOp {
Like, Like,
} }
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Enum, Eq, Hash, PartialEq, Serialize)]
pub enum NumberField { pub enum NumberField {
DiscNumber, DiscNumber,
TrackNumber, TrackNumber,

View file

@ -1,4 +1,5 @@
use chumsky::Parser; use chumsky::Parser;
use enum_map::EnumMap;
use lasso2::{RodeoReader, Spur}; use lasso2::{RodeoReader, Spur};
use nohash_hasher::{IntMap, IntSet}; use nohash_hasher::{IntMap, IntSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -24,8 +25,8 @@ use super::{
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Search { pub struct Search {
text_fields: HashMap<TextField, TextFieldIndex>, text_fields: EnumMap<TextField, TextFieldIndex>,
number_fields: HashMap<NumberField, NumberFieldIndex>, number_fields: EnumMap<NumberField, NumberFieldIndex>,
} }
impl Default for Search { impl Default for Search {
@ -149,13 +150,9 @@ impl Search {
operator: TextOp, operator: TextOp,
value: &str, value: &str,
) -> IntSet<SongKey> { ) -> IntSet<SongKey> {
let Some(field_index) = self.text_fields.get(&field) else {
return IntSet::default();
};
match operator { match operator {
TextOp::Eq => field_index.find_exact(canon, value), TextOp::Eq => self.text_fields[field].find_exact(canon, value),
TextOp::Like => field_index.find_like(strings, value), TextOp::Like => self.text_fields[field].find_like(strings, value),
} }
} }
@ -165,10 +162,7 @@ impl Search {
operator: NumberOp, operator: NumberOp,
value: i32, value: i32,
) -> IntSet<SongKey> { ) -> IntSet<SongKey> {
let Some(field_index) = self.number_fields.get(&field) else { self.number_fields[field].find(value as i64, operator)
return IntSet::default();
};
field_index.find(value as i64, operator)
} }
} }
@ -267,8 +261,8 @@ impl NumberFieldIndex {
#[derive(Default)] #[derive(Default)]
pub struct Builder { pub struct Builder {
text_fields: HashMap<TextField, TextFieldIndex>, text_fields: EnumMap<TextField, TextFieldIndex>,
number_fields: HashMap<NumberField, NumberFieldIndex>, number_fields: EnumMap<NumberField, NumberFieldIndex>,
} }
impl Builder { impl Builder {
@ -278,10 +272,7 @@ impl Builder {
}; };
if let (Some(str), Some(spur)) = (&scanner_song.album, storage_song.album) { if let (Some(str), Some(spur)) = (&scanner_song.album, storage_song.album) {
self.text_fields self.text_fields[TextField::Album].insert(str, spur, song_key);
.entry(TextField::Album)
.or_default()
.insert(str, spur, song_key);
} }
for (str, spur) in scanner_song for (str, spur) in scanner_song
@ -289,17 +280,11 @@ impl Builder {
.iter() .iter()
.zip(storage_song.album_artists.iter()) .zip(storage_song.album_artists.iter())
{ {
self.text_fields self.text_fields[TextField::AlbumArtist].insert(str, *spur, song_key);
.entry(TextField::AlbumArtist)
.or_default()
.insert(str, *spur, song_key);
} }
for (str, spur) in scanner_song.artists.iter().zip(storage_song.artists.iter()) { for (str, spur) in scanner_song.artists.iter().zip(storage_song.artists.iter()) {
self.text_fields self.text_fields[TextField::Artist].insert(str, *spur, song_key);
.entry(TextField::Artist)
.or_default()
.insert(str, *spur, song_key);
} }
for (str, spur) in scanner_song for (str, spur) in scanner_song
@ -307,31 +292,19 @@ impl Builder {
.iter() .iter()
.zip(storage_song.composers.iter()) .zip(storage_song.composers.iter())
{ {
self.text_fields self.text_fields[TextField::Composer].insert(str, *spur, song_key);
.entry(TextField::Composer)
.or_default()
.insert(str, *spur, song_key);
} }
if let Some(disc_number) = &scanner_song.disc_number { if let Some(disc_number) = &scanner_song.disc_number {
self.number_fields self.number_fields[NumberField::DiscNumber].insert(*disc_number, song_key);
.entry(NumberField::DiscNumber)
.or_default()
.insert(*disc_number, song_key);
} }
for (str, spur) in scanner_song.genres.iter().zip(storage_song.genres.iter()) { for (str, spur) in scanner_song.genres.iter().zip(storage_song.genres.iter()) {
self.text_fields self.text_fields[TextField::Genre].insert(str, *spur, song_key);
.entry(TextField::Genre)
.or_default()
.insert(str, *spur, song_key);
} }
for (str, spur) in scanner_song.labels.iter().zip(storage_song.labels.iter()) { for (str, spur) in scanner_song.labels.iter().zip(storage_song.labels.iter()) {
self.text_fields self.text_fields[TextField::Label].insert(str, *spur, song_key);
.entry(TextField::Label)
.or_default()
.insert(str, *spur, song_key);
} }
for (str, spur) in scanner_song for (str, spur) in scanner_song
@ -339,37 +312,25 @@ impl Builder {
.iter() .iter()
.zip(storage_song.lyricists.iter()) .zip(storage_song.lyricists.iter())
{ {
self.text_fields self.text_fields[TextField::Lyricist].insert(str, *spur, song_key);
.entry(TextField::Lyricist)
.or_default()
.insert(str, *spur, song_key);
} }
self.text_fields.entry(TextField::Path).or_default().insert( self.text_fields[TextField::Path].insert(
scanner_song.virtual_path.to_string_lossy().as_ref(), scanner_song.virtual_path.to_string_lossy().as_ref(),
storage_song.virtual_path.0, storage_song.virtual_path.0,
song_key, song_key,
); );
if let (Some(str), Some(spur)) = (&scanner_song.title, storage_song.title) { if let (Some(str), Some(spur)) = (&scanner_song.title, storage_song.title) {
self.text_fields self.text_fields[TextField::Title].insert(str, spur, song_key);
.entry(TextField::Title)
.or_default()
.insert(str, spur, song_key);
} }
if let Some(track_number) = &scanner_song.track_number { if let Some(track_number) = &scanner_song.track_number {
self.number_fields self.number_fields[NumberField::TrackNumber].insert(*track_number, song_key);
.entry(NumberField::TrackNumber)
.or_default()
.insert(*track_number, song_key);
} }
if let Some(year) = &scanner_song.year { if let Some(year) = &scanner_song.year {
self.number_fields self.number_fields[NumberField::Year].insert(*year, song_key);
.entry(NumberField::Year)
.or_default()
.insert(*year, song_key);
} }
} }