This commit is contained in:
Aleksandr 2025-12-22 05:20:06 +03:00
parent 29574637da
commit 843ae33a3f
13 changed files with 209 additions and 22 deletions

View file

@ -8,6 +8,7 @@ pub mod messages;
pub mod threads;
pub mod marks;
pub mod tabs;
pub mod auth;
pub mod authors;

View file

@ -51,19 +51,11 @@ pub trait BoolExt: Sized {
impl BoolExt for bool {
fn true_or<E>(self, err: E) -> Result<(), E> {
if self {
Ok(())
} else {
Err(err)
}
if self { Ok(()) } else { Err(err) }
}
fn false_or<E>(self, err: E) -> Result<(), E> {
if self {
Err(err)
} else {
Ok(())
}
if self { Err(err) } else { Ok(()) }
}
}
@ -79,7 +71,7 @@ impl<T> OptExt for Option<T> {
fn none_or<E>(self, f: impl FnOnce(Self::Inside) -> E) -> Result<(), E> {
match self {
Some(v) => Err(f(v)),
None => Ok(())
None => Ok(()),
}
}
}

35
core/src/errors/tabs.rs Normal file
View file

@ -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,
}

View file

@ -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<mark::Tag, str::CompactString>,
pub badges: HashMap<mark::Badge, str::CompactString>,
}
#[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)]

View file

@ -3,6 +3,7 @@ use crate::errors::Generic;
pub type Response<O, E> = Result<O, Generic<E>>;
pub mod marks;
pub mod tabs;
pub mod boards;
pub mod messages;

116
core/src/requests/tabs.rs Normal file
View file

@ -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<Tab>,
}
#[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<entity::Id>,
#[serde(default)]
pub limit: Limit,
#[serde(default)]
pub resolve_marks: bool,
}
#[data]
pub enum Ok {
Games {
items: Vec<tab::TabItem<game::Game>>,
#[serde(default)]
marks: game::Marks,
},
Authors(Vec<tab::TabItem<author::Author>>),
}
#[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),
}
}

View file

@ -33,4 +33,6 @@ impl<S: IsSession> Session<S> {project!{
fn tags() -> marks::Tags;
fn genres() -> marks::Genres;
fn badges() -> marks::Badges;
fn tabs() -> tabs::Tabs;
}}

View file

@ -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
;
}

16
core/src/service/tabs.rs Normal file
View file

@ -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<list::Args, Ok = list::Ok, Err = list::Err>;
fn insert(&mut self) -> impl CallStep<insert::Args, Ok = insert::Ok, Err = insert::Err>;
fn delete(&mut self) -> impl CallStep<delete::Args, Ok = delete::Ok, Err = delete::Err>;
fn list_items(
&mut self,
) -> impl CallStep<list_items::Args, Ok = list_items::Ok, Err = list_items::Err>;
}

View file

@ -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<mark::Tag, CompactString>,
pub badges: HashMap<mark::Badge, CompactString>,
}
#[data]
pub struct Game {
pub id: Id,

View file

@ -7,6 +7,7 @@ pub mod message;
pub mod thread;
pub mod mark;
pub mod tab;
pub mod author;
pub mod user;

20
core/src/types/tab.rs Normal file
View file

@ -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<I> {
pub item: I,
pub created_at: Date,
}
#[data(copy, ord)]
pub enum Kind {
#[display("games")]
Games,
#[display("authors")]
Authors,
}

View file

@ -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);
};