Skip to content

Commit

Permalink
Search indexing WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
agersant committed Sep 22, 2024
1 parent f3fa032 commit 1d60c29
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 75 deletions.
2 changes: 2 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ pub enum Error {
AlbumNotFound,
#[error("Song not found")]
SongNotFound,
#[error("Invalid search query syntax")]
SearchQueryParseError,
#[error("Playlist not found")]
PlaylistNotFound,
#[error("No embedded artwork was found in `{0}`")]
Expand Down
32 changes: 25 additions & 7 deletions src/app/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod storage;

pub use browser::File;
pub use collection::{Album, AlbumHeader, Artist, ArtistHeader, Song};
use storage::{AlbumKey, ArtistKey, InternPath, SongKey};
use storage::{store_song, AlbumKey, ArtistKey, InternPath, SongKey};

#[derive(Clone)]
pub struct Manager {
Expand Down Expand Up @@ -254,8 +254,16 @@ impl Manager {
.unwrap()
}

pub async fn search(&self, _query: &str) -> Result<Vec<PathBuf>, Error> {
todo!();
pub async fn search(&self, query: String) -> Result<Vec<PathBuf>, Error> {
spawn_blocking({
let index_manager = self.clone();
move || {
let index = index_manager.index.read().unwrap();
index.search.find_songs(&index.strings, &query)
}
})
.await
.unwrap()
}
}

Expand All @@ -264,6 +272,7 @@ pub struct Index {
pub strings: RodeoReader,
pub browser: browser::Browser,
pub collection: collection::Collection,
pub search: search::Search,
}

impl Default for Index {
Expand All @@ -272,6 +281,7 @@ impl Default for Index {
strings: Rodeo::new().into_reader(),
browser: Default::default(),
collection: Default::default(),
search: Default::default(),
}
}
}
Expand All @@ -281,6 +291,7 @@ pub struct Builder {
minuscules: HashMap<String, Spur>,
browser_builder: browser::Builder,
collection_builder: collection::Builder,
search_builder: search::Builder,
}

impl Builder {
Expand All @@ -290,6 +301,7 @@ impl Builder {
minuscules: HashMap::default(),
browser_builder: browser::Builder::default(),
collection_builder: collection::Builder::default(),
search_builder: search::Builder::default(),
}
}

Expand All @@ -298,16 +310,22 @@ impl Builder {
.add_directory(&mut self.strings, directory);
}

pub fn add_song(&mut self, song: scanner::Song) {
self.browser_builder.add_song(&mut self.strings, &song);
self.collection_builder
.add_song(&mut self.strings, &mut self.minuscules, &song);
pub fn add_song(&mut self, scanner_song: scanner::Song) {
if let Some(storage_song) =
store_song(&mut self.strings, &mut self.minuscules, &scanner_song)
{
self.browser_builder
.add_song(&mut self.strings, &scanner_song);
self.collection_builder.add_song(&storage_song);
self.search_builder.add_song(&scanner_song, &storage_song);
}
}

pub fn build(self) -> Index {
Index {
browser: self.browser_builder.build(),
collection: self.collection_builder.build(),
search: self.search_builder.build(),
strings: self.strings.into_reader(),
}
}
Expand Down
26 changes: 10 additions & 16 deletions src/app/index/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ use std::{
path::PathBuf,
};

use lasso2::{Rodeo, RodeoReader, Spur};
use lasso2::{RodeoReader, Spur};
use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng};
use serde::{Deserialize, Serialize};
use tinyvec::TinyVec;
use unicase::UniCase;

use crate::app::index::storage::{self, store_song, AlbumKey, ArtistKey, SongKey};
use crate::app::scanner;
use crate::app::index::storage::{self, AlbumKey, ArtistKey, SongKey};

use super::storage::fetch_song;

Expand Down Expand Up @@ -226,24 +225,15 @@ pub struct Builder {
}

impl Builder {
pub fn add_song(
&mut self,
strings: &mut Rodeo,
minuscules: &mut HashMap<String, Spur>,
song: &scanner::Song,
) {
let Some(song) = store_song(strings, minuscules, song) else {
return;
};

pub fn add_song(&mut self, song: &storage::Song) {
self.add_song_to_album(&song);
self.add_song_to_artists(&song);

self.songs.insert(
SongKey {
virtual_path: song.virtual_path,
},
song,
song.clone(),
);
}

Expand Down Expand Up @@ -374,9 +364,12 @@ impl Builder {
#[cfg(test)]
mod test {

use storage::InternPath;
use lasso2::Rodeo;
use tinyvec::tiny_vec;

use crate::app::scanner;
use storage::{store_song, InternPath};

use super::*;

fn setup_test(songs: Vec<scanner::Song>) -> (Collection, RodeoReader) {
Expand All @@ -385,7 +378,8 @@ mod test {
let mut builder = Builder::default();

for song in songs {
builder.add_song(&mut strings, &mut minuscules, &song);
let song = store_song(&mut strings, &mut minuscules, &song).unwrap();
builder.add_song(&song);
}

let browser = builder.build();
Expand Down
23 changes: 4 additions & 19 deletions src/app/index/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use chumsky::{
text::{int, keyword, whitespace, TextParser},
Parser,
};
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TextField {
Album,
AlbumArtist,
Expand All @@ -23,12 +24,10 @@ pub enum TextField {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TextOp {
Eq,
NotEq,
Like,
NotLike,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum NumberField {
DiscNumber,
TrackNumber,
Expand Down Expand Up @@ -95,13 +94,7 @@ pub fn make_parser() -> impl Parser<char, Expr, Error = Simple<char>> {
))
.padded();

let text_op = choice((
just("=").to(TextOp::Eq),
just("!=").to(TextOp::NotEq),
just("%").to(TextOp::Like),
just("!%").to(TextOp::NotLike),
))
.padded();
let text_op = choice((just("=").to(TextOp::Eq), just("%").to(TextOp::Like))).padded();

let text_cmp = text_field
.then(text_op)
Expand Down Expand Up @@ -248,18 +241,10 @@ fn can_parse_text_operators() {
parser.parse(r#"album = "legendary tales""#).unwrap(),
Expr::TextCmp(TextField::Album, TextOp::Eq, "legendary tales".to_owned()),
);
assert_eq!(
parser.parse(r#"album != legendary"#).unwrap(),
Expr::TextCmp(TextField::Album, TextOp::NotEq, "legendary".to_owned()),
);
assert_eq!(
parser.parse(r#"album % "legendary tales""#).unwrap(),
Expr::TextCmp(TextField::Album, TextOp::Like, "legendary tales".to_owned()),
);
assert_eq!(
parser.parse(r#"album !% "legendary""#).unwrap(),
Expr::TextCmp(TextField::Album, TextOp::NotLike, "legendary".to_owned()),
);
}

#[test]
Expand Down
Loading

0 comments on commit 1d60c29

Please sign in to comment.