aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-19 18:17:32 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-19 18:17:32 +0100
commit3a81f654a9f49649fb6755b6e35649f0102a9572 (patch)
tree3b6be37eac969fea2b6dee0b718cc77efe2230a8
parent962309ddcb033e0032258d6badebb90415a34e3d (diff)
downloadjellything-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.rs12
-rw-r--r--common/object/src/value.rs62
-rw-r--r--common/src/node.rs6
-rw-r--r--database/src/kv/binning.rs56
-rw-r--r--database/src/lib.rs55
-rw-r--r--database/src/query_ser.rs8
-rw-r--r--import/src/plugins/musicbrainz.rs1
-rw-r--r--import/src/plugins/tmdb.rs1
-rw-r--r--import/src/plugins/trakt.rs6
-rw-r--r--import/src/plugins/vgmdb.rs1
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(());