diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-02-19 18:17:32 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-02-19 18:17:32 +0100 |
| commit | 3a81f654a9f49649fb6755b6e35649f0102a9572 (patch) | |
| tree | 3b6be37eac969fea2b6dee0b718cc77efe2230a8 | |
| parent | 962309ddcb033e0032258d6badebb90415a34e3d (diff) | |
| download | jellything-3a81f654a9f49649fb6755b6e35649f0102a9572.tar jellything-3a81f654a9f49649fb6755b6e35649f0102a9572.tar.bz2 jellything-3a81f654a9f49649fb6755b6e35649f0102a9572.tar.zst | |
all idents as string; move value type; add cow to queries
| -rw-r--r-- | common/object/src/lib.rs | 12 | ||||
| -rw-r--r-- | common/object/src/value.rs | 62 | ||||
| -rw-r--r-- | common/src/node.rs | 6 | ||||
| -rw-r--r-- | database/src/kv/binning.rs | 56 | ||||
| -rw-r--r-- | database/src/lib.rs | 55 | ||||
| -rw-r--r-- | database/src/query_ser.rs | 8 | ||||
| -rw-r--r-- | import/src/plugins/musicbrainz.rs | 1 | ||||
| -rw-r--r-- | import/src/plugins/tmdb.rs | 1 | ||||
| -rw-r--r-- | import/src/plugins/trakt.rs | 6 | ||||
| -rw-r--r-- | import/src/plugins/vgmdb.rs | 1 |
10 files changed, 106 insertions, 102 deletions
diff --git a/common/object/src/lib.rs b/common/object/src/lib.rs index 7d0c203..3e60d58 100644 --- a/common/object/src/lib.rs +++ b/common/object/src/lib.rs @@ -154,14 +154,14 @@ impl<'a> Object<'a> { Some(&values_u8[start as usize..end as usize]) } #[inline] - pub fn get_typed<T: Value<'a>>(&self, index: usize) -> Option<T> { + pub fn get_typed<T: ValueLoad<'a>>(&self, index: usize) -> Option<T> { if T::ALIGNED { T::load_aligned(self.get_aligned(index)?) } else { T::load_unaligned(self.get_unaligned(index)?) } } - pub fn get<T: Value<'a>>(&self, tag: TypedTag<T>) -> Option<T> { + pub fn get<T: ValueLoad<'a>>(&self, tag: TypedTag<T>) -> Option<T> { self.get_typed(self.find_field(tag.0)?) } pub fn keys(&self) -> KeysIter<'a> { @@ -186,7 +186,7 @@ impl<'a> Object<'a> { } } #[must_use] - pub fn extend<T: Value<'a> + Eq + Ord>( + pub fn extend<T: ValueLoad<'a> + Eq + Ord>( &self, tag: TypedTag<T>, values: impl IntoIterator<Item = T>, @@ -318,13 +318,13 @@ pub struct EntriesIter<'a, T> { index: usize, ty: PhantomData<T>, } -impl<'a, T: Value<'a>> Iterator for EntriesIter<'a, T> { +impl<'a, T: ValueLoad<'a>> Iterator for EntriesIter<'a, T> { type Item = (Tag, T); fn next(&mut self) -> Option<Self::Item> { if self.index >= self.object.tags.len() { return None; } else { - let value = self.object.get_typed(self.index)?; //? This ends the iterator early if there is any invalid field + let value = self.object.get_typed(self.index)?; let tag = self.object.tags[self.index]; self.index += 1; Some((Tag(tag), value)) @@ -338,7 +338,7 @@ pub struct FieldIter<'a, T> { tag: u32, ty: PhantomData<T>, } -impl<'a, T: Value<'a>> Iterator for FieldIter<'a, T> { +impl<'a, T: ValueLoad<'a>> Iterator for FieldIter<'a, T> { type Item = T; fn next(&mut self) -> Option<Self::Item> { if self.index >= self.object.tags.len() { diff --git a/common/object/src/value.rs b/common/object/src/value.rs index 01b0903..3db7e7c 100644 --- a/common/object/src/value.rs +++ b/common/object/src/value.rs @@ -5,8 +5,9 @@ */ use crate::{Object, ObjectBuffer, Tag}; +use std::borrow::Cow; -pub trait Value<'a>: ValueStore + Sized { +pub trait ValueLoad<'a>: ValueStore + Sized { const ALIGNED: bool; fn load_aligned(buf: &'a [u32]) -> Option<Self> { let _ = buf; @@ -53,13 +54,54 @@ impl ValueType { } } +#[derive(Debug, Clone)] +pub enum Value<'a> { + Tag(Tag), + U32(u32), + U64(u64), + I64(i64), + String(Cow<'a, str>), + Binary(Cow<'a, [u8]>), +} + +impl<'a> From<&'a str> for Value<'a> { + fn from(value: &'a str) -> Self { + Self::String(value.into()) + } +} +impl From<String> for Value<'static> { + fn from(value: String) -> Self { + Self::String(value.into()) + } +} +impl From<u32> for Value<'static> { + fn from(value: u32) -> Self { + Self::U32(value) + } +} +impl From<u64> for Value<'static> { + fn from(value: u64) -> Self { + Self::U64(value) + } +} +impl From<i64> for Value<'static> { + fn from(value: i64) -> Self { + Self::I64(value) + } +} +impl From<Tag> for Value<'static> { + fn from(value: Tag) -> Self { + Self::Tag(value) + } +} + pub trait ValueStore { fn get_type(&self) -> ValueType; fn store_aligned(&self, _buf: &mut Vec<u32>) {} fn store_unaligned(&self, _buf: &mut Vec<u8>) {} fn size(&self) -> usize; } -impl<'a> Value<'a> for &'a str { +impl<'a> ValueLoad<'a> for &'a str { const ALIGNED: bool = false; fn load_unaligned(buf: &'a [u8]) -> Option<Self> { str::from_utf8(buf).ok() @@ -76,7 +118,7 @@ impl ValueStore for &str { self.len() } } -impl Value<'_> for u32 { +impl ValueLoad<'_> for u32 { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option<Self> { buf.get(0).copied().map(u32::from_be) @@ -93,7 +135,7 @@ impl ValueStore for u32 { 4 } } -impl Value<'_> for Tag { +impl ValueLoad<'_> for Tag { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option<Self> { buf.get(0).copied().map(u32::from_be).map(Tag) @@ -110,7 +152,7 @@ impl ValueStore for Tag { 4 } } -impl Value<'_> for u64 { +impl ValueLoad<'_> for u64 { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option<Self> { let hi = u32::from_be(*buf.get(0)?) as u64; @@ -130,7 +172,7 @@ impl ValueStore for u64 { 8 } } -impl Value<'_> for f64 { +impl ValueLoad<'_> for f64 { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option<Self> { if buf.len() < 2 { @@ -156,7 +198,7 @@ impl ValueStore for f64 { 8 } } -impl Value<'_> for i64 { +impl ValueLoad<'_> for i64 { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option<Self> { u64::load_aligned(buf).map(|x| x as i64) @@ -173,7 +215,7 @@ impl ValueStore for i64 { 8 } } -impl<'a> Value<'a> for Object<'a> { +impl<'a> ValueLoad<'a> for Object<'a> { const ALIGNED: bool = true; fn load_aligned(buf: &'a [u32]) -> Option<Self> { Self::load(buf) @@ -204,7 +246,7 @@ impl ValueStore for ObjectBuffer { self.0.len() * 4 } } -impl<'a> Value<'a> for &'a [u8] { +impl<'a> ValueLoad<'a> for &'a [u8] { const ALIGNED: bool = false; fn load_unaligned(buf: &'a [u8]) -> Option<Self> { Some(buf) @@ -221,7 +263,7 @@ impl ValueStore for &[u8] { self.len() } } -impl<'a> Value<'a> for () { +impl<'a> ValueLoad<'a> for () { const ALIGNED: bool = true; fn load_aligned(_buf: &'a [u32]) -> Option<Self> { Some(()) diff --git a/common/src/node.rs b/common/src/node.rs index 5e52a4c..b02f8e8 100644 --- a/common/src/node.rs +++ b/common/src/node.rs @@ -79,15 +79,15 @@ fields! { IDENT_TRAKT_SHOW: &str = b"trsh"; IDENT_TRAKT_SEASON: &str = b"trse"; IDENT_TRAKT_EPISODE: &str = b"trep"; - IDENT_TRAKT_PERSON: u64 = b"trpe"; + IDENT_TRAKT_PERSON: &str = b"trpe"; IDENT_IMDB: &str = b"imdb"; IDENT_IMDB_PERSON: &str = b"impe"; IDENT_TMDB_SERIES: &str = b"tmse"; IDENT_TMDB_MOVIE: &str = b"tmmv"; - IDENT_TMDB_PERSON: u64 = b"tmpe"; + IDENT_TMDB_PERSON: &str = b"tmpe"; IDENT_TVDB: &str = b"tvdb"; IDENT_OMDB: &str = b"omdb"; - IDENT_VGMDB_ARTIST: u64 = b"vgar"; + IDENT_VGMDB_ARTIST: &str = b"vgar"; IDENT_WIKIDATA: &str = b"wkdt"; } diff --git a/database/src/kv/binning.rs b/database/src/kv/binning.rs index c41d6e9..253bb5c 100644 --- a/database/src/kv/binning.rs +++ b/database/src/kv/binning.rs @@ -51,7 +51,7 @@ impl BinningComponent { } } -impl Filter { +impl Filter<'_> { pub fn get_binnings(&self) -> Vec<Binning> { self.get_bins_inner() .into_iter() @@ -88,7 +88,7 @@ impl Filter { Filter::Match(path, value) => { vec![vec![(BinningComponent::Match(path.to_owned()), { let mut co = Vec::new(); - value.write_with_len(&mut co); + write_value_with_len(value, &mut co); co })]] } @@ -99,33 +99,31 @@ impl Filter { } } -impl Value { - pub fn write_with_len(&self, out: &mut Vec<u8>) { - match self { - Value::Tag(tag) => { - out.extend(4u32.to_be_bytes()); - out.extend(tag.0.to_be_bytes()); - } - Value::U32(x) => { - out.extend(4u32.to_be_bytes()); - out.extend(x.to_be_bytes()); - } - Value::U64(x) => { - out.extend(8u32.to_be_bytes()); - out.extend(x.to_be_bytes()); - } - Value::I64(x) => { - out.extend(8u32.to_be_bytes()); - out.extend(x.to_be_bytes()); - } - Value::String(s) => { - out.extend((s.len() as u32).to_be_bytes()); - out.extend(s.as_bytes()); - } - Value::Binary(s) => { - out.extend((s.len() as u32).to_be_bytes()); - out.extend(s); - } +pub fn write_value_with_len(value: &Value, out: &mut Vec<u8>) { + match value { + Value::Tag(tag) => { + out.extend(4u32.to_be_bytes()); + out.extend(tag.0.to_be_bytes()); + } + Value::U32(x) => { + out.extend(4u32.to_be_bytes()); + out.extend(x.to_be_bytes()); + } + Value::U64(x) => { + out.extend(8u32.to_be_bytes()); + out.extend(x.to_be_bytes()); + } + Value::I64(x) => { + out.extend(8u32.to_be_bytes()); + out.extend(x.to_be_bytes()); + } + Value::String(s) => { + out.extend((s.len() as u32).to_be_bytes()); + out.extend(s.as_bytes()); + } + Value::Binary(s) => { + out.extend((s.len() as u32).to_be_bytes()); + out.extend(&**s); } } } diff --git a/database/src/lib.rs b/database/src/lib.rs index 2ecf3c6..ea12447 100644 --- a/database/src/lib.rs +++ b/database/src/lib.rs @@ -9,7 +9,7 @@ pub mod query_ser; pub mod test_shared; use anyhow::Result; -use jellyobject::{ObjectBuffer, Path, Tag}; +use jellyobject::{ObjectBuffer, Path, Value}; pub type RowNum = u64; pub type RowIter = Box<dyn Iterator<Item = Result<(RowNum, Vec<u8>)>>>; @@ -33,8 +33,8 @@ pub trait Transaction { } #[derive(Default, Clone)] -pub struct Query { - pub filter: Filter, +pub struct Query<'a> { + pub filter: Filter<'a>, pub sort: Sort, } @@ -70,52 +70,11 @@ pub enum SortOrder { } #[derive(Debug, Clone, Default)] -pub enum Filter { +pub enum Filter<'a> { #[default] True, - All(Vec<Filter>), - Any(Vec<Filter>), - Match(Path, Value), + All(Vec<Filter<'a>>), + Any(Vec<Filter<'a>>), + Match(Path, Value<'a>), Has(Path), } - -#[derive(Debug, Clone)] -pub enum Value { - Tag(Tag), - U32(u32), - U64(u64), - I64(i64), - String(String), - Binary(Vec<u8>), -} - -impl From<&str> for Value { - fn from(value: &str) -> Self { - Self::String(value.to_owned()) - } -} -impl From<String> for Value { - fn from(value: String) -> Self { - Self::String(value) - } -} -impl From<u32> for Value { - fn from(value: u32) -> Self { - Self::U32(value) - } -} -impl From<u64> for Value { - fn from(value: u64) -> Self { - Self::U64(value) - } -} -impl From<i64> for Value { - fn from(value: i64) -> Self { - Self::I64(value) - } -} -impl From<Tag> for Value { - fn from(value: Tag) -> Self { - Self::Tag(value) - } -} diff --git a/database/src/query_ser.rs b/database/src/query_ser.rs index d51ef64..78eee09 100644 --- a/database/src/query_ser.rs +++ b/database/src/query_ser.rs @@ -4,9 +4,11 @@ Copyright (C) 2026 metamuffin <metamuffin.org> */ -use crate::{Filter, MultiBehaviour, Query, Sort, SortOrder, Value, ValueSort}; +use jellyobject::Value; -impl Query { +use crate::{Filter, MultiBehaviour, Query, Sort, SortOrder, ValueSort}; + +impl Query<'_> { pub fn show(&self) -> String { let mut o = String::new(); if !matches!(self.filter, Filter::True) { @@ -18,7 +20,7 @@ impl Query { o } } -impl Filter { +impl Filter<'_> { pub fn show(&self) -> String { match self { Filter::True => "TRUE".to_string(), diff --git a/import/src/plugins/musicbrainz.rs b/import/src/plugins/musicbrainz.rs index 9f7b08c..4dfd974 100644 --- a/import/src/plugins/musicbrainz.rs +++ b/import/src/plugins/musicbrainz.rs @@ -455,7 +455,6 @@ impl MusicBrainz { if let Some(url) = url && let Some(id) = url.strip_prefix("https://vgmdb.net/artist/") { - let id = id.parse::<u64>().context("parse vgmdb id")?; node = node .as_object() .update(NO_IDENTIFIERS, |ids| ids.insert(IDENT_VGMDB_ARTIST, id)) diff --git a/import/src/plugins/tmdb.rs b/import/src/plugins/tmdb.rs index dfdf020..ab0a679 100644 --- a/import/src/plugins/tmdb.rs +++ b/import/src/plugins/tmdb.rs @@ -324,6 +324,7 @@ impl Tmdb { else { return Ok(()); }; + let id = id.parse()?; let images = self.person_image(&ct.ic.cache, id, ct.rt)?; let Some(prof) = images.profiles.first() else { diff --git a/import/src/plugins/trakt.rs b/import/src/plugins/trakt.rs index 021ffe9..1d01436 100644 --- a/import/src/plugins/trakt.rs +++ b/import/src/plugins/trakt.rs @@ -524,9 +524,11 @@ impl Trakt { c = c.as_object().insert(NO_VISIBILITY, VISI_VISIBLE); c = c.as_object().insert(NO_TITLE, &ap.person.name); c = c.as_object().update(NO_IDENTIFIERS, |ids| { - let mut ids = ids.insert(IDENT_TRAKT_PERSON, traktid); + let mut ids = ids.insert(IDENT_TRAKT_PERSON, &traktid.to_string()); if let Some(tmdbid) = ap.person.ids.tmdb { - ids = ids.as_object().insert(IDENT_TMDB_PERSON, tmdbid); + ids = ids + .as_object() + .insert(IDENT_TMDB_PERSON, &tmdbid.to_string()); } if let Some(imdbid) = &ap.person.ids.imdb { ids = ids.as_object().insert(IDENT_IMDB_PERSON, imdbid); diff --git a/import/src/plugins/vgmdb.rs b/import/src/plugins/vgmdb.rs index 8221692..b7630d2 100644 --- a/import/src/plugins/vgmdb.rs +++ b/import/src/plugins/vgmdb.rs @@ -156,6 +156,7 @@ impl ImportPlugin for Vgmdb { else { return Ok(()); }; + let id = id.parse()?; let Some(image) = self.get_artist_image(&ct.ic.cache, id, ct.rt)? else { return Ok(()); |