From 843ae33a3f52f70da826f24ae95b5a2dc3daa618 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Mon, 22 Dec 2025 05:20:06 +0300 Subject: [PATCH] add tabs --- core/src/errors.rs | 1 + core/src/errors/ext.rs | 14 +--- core/src/errors/tabs.rs | 35 ++++++++++ core/src/requests/games.rs | 11 +--- core/src/requests/mod.rs | 1 + core/src/requests/tabs.rs | 116 ++++++++++++++++++++++++++++++++++ core/src/service/api_looks.rs | 2 + core/src/service/mod.rs | 2 + core/src/service/tabs.rs | 16 +++++ core/src/types/game.rs | 9 +++ core/src/types/mod.rs | 1 + core/src/types/tab.rs | 20 ++++++ http/src/requests/marks.rs | 3 +- 13 files changed, 209 insertions(+), 22 deletions(-) create mode 100644 core/src/errors/tabs.rs create mode 100644 core/src/requests/tabs.rs create mode 100644 core/src/service/tabs.rs create mode 100644 core/src/types/tab.rs diff --git a/core/src/errors.rs b/core/src/errors.rs index bdb9e11..7ca9557 100644 --- a/core/src/errors.rs +++ b/core/src/errors.rs @@ -8,6 +8,7 @@ pub mod messages; pub mod threads; pub mod marks; +pub mod tabs; pub mod auth; pub mod authors; diff --git a/core/src/errors/ext.rs b/core/src/errors/ext.rs index 54d5e24..f8b3706 100644 --- a/core/src/errors/ext.rs +++ b/core/src/errors/ext.rs @@ -51,19 +51,11 @@ pub trait BoolExt: Sized { impl BoolExt for bool { fn true_or(self, err: E) -> Result<(), E> { - if self { - Ok(()) - } else { - Err(err) - } + if self { Ok(()) } else { Err(err) } } fn false_or(self, err: E) -> Result<(), E> { - if self { - Err(err) - } else { - Ok(()) - } + if self { Err(err) } else { Ok(()) } } } @@ -79,7 +71,7 @@ impl OptExt for Option { fn none_or(self, f: impl FnOnce(Self::Inside) -> E) -> Result<(), E> { match self { Some(v) => Err(f(v)), - None => Ok(()) + None => Ok(()), } } } diff --git a/core/src/errors/tabs.rs b/core/src/errors/tabs.rs new file mode 100644 index 0000000..580b6d2 --- /dev/null +++ b/core/src/errors/tabs.rs @@ -0,0 +1,35 @@ +use eva::data; + +use crate::types::{entity, tab}; + +#[data(error, display("no such tab: {id}"))] +pub struct NoSuchTab { + pub id: tab::Id, +} + +#[data(error, display("the item {item} already exists in {id}"))] +pub struct Duplicate { + pub id: tab::Id, + pub item: entity::Id, +} + +#[data(error, display("the item {item} was not found in {id}"))] +pub struct NoSuchItem { + pub id: tab::Id, + pub item: entity::Id, +} + +#[data(error, display("invalid tab kind, expected {expected}, but got {got}"))] +pub struct InvalidKind { + pub expected: tab::Kind, + pub got: tab::Kind, +} + +#[data( + copy, + error, + display("invalid ID, expected game or author, got: {got}") +)] +pub struct InvalidItemId { + pub got: entity::Kind, +} diff --git a/core/src/requests/games.rs b/core/src/requests/games.rs index f03ec32..f3d80d0 100644 --- a/core/src/requests/games.rs +++ b/core/src/requests/games.rs @@ -3,8 +3,6 @@ use crate::{ types::{Patch, True, author, file, game, mark}, }; -use std::collections::HashMap; - use eva::{array, data, int, perfect_derive, str, time}; pub mod update { @@ -177,15 +175,10 @@ pub mod create { pub mod get { use super::*; - #[data] - pub struct Marks { - pub tags: HashMap, - pub badges: HashMap, - } - #[data] pub struct Args { pub game: game::Selector, + pub resolve_marks: bool, } #[data] @@ -195,7 +188,7 @@ pub mod get { // - comments // - downloads pub game: game::Game, - pub marks: Marks, + pub marks: game::Marks, } #[data(error)] diff --git a/core/src/requests/mod.rs b/core/src/requests/mod.rs index fc9760d..71e9f2a 100644 --- a/core/src/requests/mod.rs +++ b/core/src/requests/mod.rs @@ -3,6 +3,7 @@ use crate::errors::Generic; pub type Response = Result>; pub mod marks; +pub mod tabs; pub mod boards; pub mod messages; diff --git a/core/src/requests/tabs.rs b/core/src/requests/tabs.rs new file mode 100644 index 0000000..61d58f1 --- /dev/null +++ b/core/src/requests/tabs.rs @@ -0,0 +1,116 @@ +use eva::{data, int}; + +use crate::{ + errors, + types::{True, author, entity, game, tab}, +}; + +pub mod list { + use super::*; + + #[data] + #[derive(Default)] + pub struct Args { + #[serde(default)] + pub resolve_marks: bool, + } + + #[data] + pub enum Tab { + Games(tab::Id), + Authors(tab::Id), + } + + #[data] + pub struct Ok { + pub tabs: Vec, + } + + #[data(error, display("_"))] + pub enum Err {} +} + +pub mod list_items { + use super::*; + + #[int(u8, 1..=64)] + pub enum Limit {} + + impl Default for Limit { + fn default() -> Self { + Self::POS16 + } + } + + #[data] + pub struct Args { + pub tab: tab::Id, + pub start_from: Option, + #[serde(default)] + pub limit: Limit, + #[serde(default)] + pub resolve_marks: bool, + } + + #[data] + pub enum Ok { + Games { + items: Vec>, + #[serde(default)] + marks: game::Marks, + }, + Authors(Vec>), + } + + #[data(error)] + pub enum Err { + #[display("{_0}")] + InvalidItemId(#[from] errors::tabs::InvalidItemId), + #[display("{_0}")] + NoSuchTab(#[from] errors::tabs::NoSuchTab), + } +} + +pub mod insert { + use super::*; + + #[data] + pub struct Args { + pub id: tab::Id, + pub item: entity::Id, + } + + pub type Ok = True; + + #[data(error)] + pub enum Err { + #[display("{_0}")] + InvalidKind(#[from] errors::tabs::InvalidKind), + #[display("{_0}")] + NoSuchTab(#[from] errors::tabs::NoSuchTab), + #[display("{_0}")] + InvalidItemId(#[from] errors::tabs::InvalidItemId), + } +} + +pub mod delete { + use super::*; + + #[data] + pub struct Args { + pub id: tab::Id, + pub item: entity::Id, + } + + pub type Ok = True; + + #[data(error)] + pub enum Err { + #[display("{_0}")] + InvalidItemId(#[from] errors::tabs::InvalidItemId), + #[display("{_0}")] + NoSuchItem(#[from] errors::tabs::NoSuchItem), + #[display("{_0}")] + NoSuchTab(#[from] errors::tabs::NoSuchTab), + } +} diff --git a/core/src/service/api_looks.rs b/core/src/service/api_looks.rs index b90898e..68f9ba8 100644 --- a/core/src/service/api_looks.rs +++ b/core/src/service/api_looks.rs @@ -33,4 +33,6 @@ impl Session {project!{ fn tags() -> marks::Tags; fn genres() -> marks::Genres; fn badges() -> marks::Badges; + + fn tabs() -> tabs::Tabs; }} diff --git a/core/src/service/mod.rs b/core/src/service/mod.rs index e650e95..40930ab 100644 --- a/core/src/service/mod.rs +++ b/core/src/service/mod.rs @@ -7,6 +7,7 @@ pub use self::api_looks::Session; mod api_looks; pub mod marks; +pub mod tabs; pub mod boards; pub mod messages; @@ -38,6 +39,7 @@ trait_set! { + marks::Tags + marks::Genres + marks::Badges + + tabs::Tabs ; } diff --git a/core/src/service/tabs.rs b/core/src/service/tabs.rs new file mode 100644 index 0000000..59754df --- /dev/null +++ b/core/src/service/tabs.rs @@ -0,0 +1,16 @@ +use eva::auto_impl; + +use crate::{ + requests::tabs::{delete, insert, list, list_items}, + service::CallStep, +}; + +#[auto_impl(&mut)] +pub trait Tabs: Send + Sync { + fn list(&mut self) -> impl CallStep; + fn insert(&mut self) -> impl CallStep; + fn delete(&mut self) -> impl CallStep; + fn list_items( + &mut self, + ) -> impl CallStep; +} diff --git a/core/src/types/game.rs b/core/src/types/game.rs index a618a8e..39649c1 100644 --- a/core/src/types/game.rs +++ b/core/src/types/game.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use eva::{array, data, int, str, str::CompactString, time::Date}; use crate::types::{author, entity::define_eid, file, mark, slug, user}; @@ -71,6 +73,13 @@ pub enum Publication { Verified(PubVerified), } +#[data] +#[derive(Default)] +pub struct Marks { + pub tags: HashMap, + pub badges: HashMap, +} + #[data] pub struct Game { pub id: Id, diff --git a/core/src/types/mod.rs b/core/src/types/mod.rs index 414ea29..94cacd5 100644 --- a/core/src/types/mod.rs +++ b/core/src/types/mod.rs @@ -7,6 +7,7 @@ pub mod message; pub mod thread; pub mod mark; +pub mod tab; pub mod author; pub mod user; diff --git a/core/src/types/tab.rs b/core/src/types/tab.rs new file mode 100644 index 0000000..c9fc829 --- /dev/null +++ b/core/src/types/tab.rs @@ -0,0 +1,20 @@ +use eva::{data, str, time::Date}; + +use crate::types::slug; + +#[str(newtype, copy)] +pub struct Id(slug::LowerSlug<23>); + +#[data] +pub struct TabItem { + pub item: I, + pub created_at: Date, +} + +#[data(copy, ord)] +pub enum Kind { + #[display("games")] + Games, + #[display("authors")] + Authors, +} diff --git a/http/src/requests/marks.rs b/http/src/requests/marks.rs index e00d23e..3dad7dc 100644 --- a/http/src/requests/marks.rs +++ b/http/src/requests/marks.rs @@ -48,11 +48,10 @@ status_code::direct!(reqs::list_badges::Ok => OK); status_code::map!(reqs::list_badges::Err => []); const _: () = { - use viendesu_core::errors::marks::*; use status_code::*; + use viendesu_core::errors::marks::*; direct!(NoSuchTag => NOT_FOUND); direct!(NoSuchGenre => NOT_FOUND); direct!(NoSuchBadge => NOT_FOUND); }; -