This commit is contained in:
Aleksandr 2025-12-14 23:29:36 +03:00
parent 360675f6f9
commit a67e3d1d8c
11 changed files with 109 additions and 46 deletions

View file

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

18
core/src/errors/marks.rs Normal file
View file

@ -0,0 +1,18 @@
use eva::data;
use crate::types::mark;
#[data(error, display("no such tag: {tag}"))]
pub struct NoSuchTag {
pub tag: mark::Tag,
}
#[data(error, display("no such genre: {genre}"))]
pub struct NoSuchGenre {
pub genre: mark::Genre,
}
#[data(error, display("no such badge: {badge}"))]
pub struct NoSuchBadge {
pub badge: mark::Badge,
}

View file

@ -1,6 +1,6 @@
use crate::{
errors,
types::{Patch, True, author, file, game},
types::{Patch, True, author, file, game, mark},
};
use std::collections::HashMap;
@ -23,9 +23,9 @@ pub mod update {
pub description: Patch<Option<game::Description>>,
pub slug: Patch<game::Slug>,
pub thumbnail: Patch<Option<file::Id>>,
pub genres: Patch<game::Genres>,
pub badges: Patch<game::Badges>,
pub tags: Patch<game::Tags>,
pub genres: Patch<mark::Genres>,
pub badges: Patch<mark::Badges>,
pub tags: Patch<mark::Tags>,
pub screenshots: Patch<game::Screenshots>,
pub published: Patch<bool>,
}
@ -37,6 +37,12 @@ pub mod update {
pub enum Err {
#[display("{_0}")]
NotFound(#[from] errors::games::NotFound),
#[display("{_0}")]
NoSuchTag(#[from] errors::marks::NoSuchTag),
#[display("{_0}")]
NoSuchBadge(#[from] errors::marks::NoSuchBadge),
#[display("{_0}")]
NoSuchGenre(#[from] errors::marks::NoSuchGenre),
}
}
@ -53,9 +59,9 @@ pub mod search {
#[data]
#[derive(Default)]
pub struct Marks {
pub tags: Logic<game::Tag, 16>,
pub genres: Logic<game::Genre, 16>,
pub badges: Logic<game::Badge, 16>,
pub tags: Logic<mark::Tag, 16>,
pub genres: Logic<mark::Genre, 16>,
pub badges: Logic<mark::Badge, 16>,
}
type SortKey<K> = (K, game::Id);
@ -141,6 +147,10 @@ pub mod create {
pub description: Option<game::Description>,
pub thumbnail: Option<file::Id>,
pub author: author::Id,
#[serde(default)]
pub tags: mark::Tags,
#[serde(default)]
pub genres: mark::Genres,
pub slug: Option<game::Slug>,
pub vndb: Option<game::VndbId>,
pub release_date: Option<game::ReleaseDate>,
@ -157,6 +167,10 @@ pub mod create {
NoSuchAuthor(#[from] errors::authors::NotFound),
#[display("{_0}")]
AlreadyTaken(#[from] errors::games::AlreadyTaken),
#[display("{_0}")]
NoSuchTag(#[from] errors::marks::NoSuchTag),
#[display("{_0}")]
NoSuchGenre(#[from] errors::marks::NoSuchGenre),
}
}
@ -165,8 +179,8 @@ pub mod get {
#[data]
pub struct Marks {
pub tags: HashMap<game::Tag, str::CompactString>,
pub badges: HashMap<game::Badge, str::CompactString>,
pub tags: HashMap<mark::Tag, str::CompactString>,
pub badges: HashMap<mark::Badge, str::CompactString>,
}
#[data]

View file

@ -1,4 +1,4 @@
use crate::types::game;
use crate::types::mark;
use eva::{array, data, str};
@ -18,7 +18,7 @@ pub mod add_tag {
#[data]
pub struct Ok {
pub id: game::Tag,
pub id: mark::Tag,
}
#[data(error, display("_"))]
@ -35,7 +35,7 @@ pub mod add_badge {
#[data]
pub struct Ok {
pub id: game::Badge,
pub id: mark::Badge,
}
#[data(error, display("_"))]
@ -52,7 +52,7 @@ pub mod list_genres {
#[data]
pub struct Ok {
pub genres: array::ImmutableHeap<game::Genre, MAX>,
pub genres: array::ImmutableHeap<mark::Genre, MAX>,
}
#[data(error, display("_"))]
@ -69,7 +69,7 @@ pub mod list_badges {
#[data]
pub struct Ok {
pub badges: Vec<TextEntry<game::Badge>>,
pub badges: Vec<TextEntry<mark::Badge>>,
}
#[data(error, display("_"))]
@ -86,7 +86,7 @@ pub mod list_tags {
#[data]
pub struct Ok {
pub tags: Vec<TextEntry<game::Tag>>,
pub tags: Vec<TextEntry<mark::Tag>>,
}
#[data(error, display("_"))]

View file

@ -1,18 +1,6 @@
use eva::{array, data, int, str, str::CompactString, time::Date};
use crate::types::{author, entity::define_eid, file, slug, user};
#[data]
#[derive(Default)]
pub struct Tags(pub array::ImmutableHeap<Tag, 64>);
#[data]
#[derive(Default)]
pub struct Genres(pub array::ImmutableHeap<Genre, 64>);
#[data]
#[derive(Default)]
pub struct Badges(pub array::ImmutableHeap<Badge, 64>);
use crate::types::{author, entity::define_eid, file, mark, slug, user};
#[data]
#[derive(Default)]
@ -100,9 +88,9 @@ pub struct Game {
pub publication: Option<Publication>,
pub screenshots: Screenshots,
pub tags: Tags,
pub genres: Genres,
pub badges: Badges,
pub tags: mark::Tags,
pub genres: mark::Genres,
pub badges: mark::Badges,
}
#[data(copy)]
@ -129,17 +117,8 @@ pub struct Votes(pub u32);
define_eid! {
/// ID of the game.
pub struct Id(Game);
/// ID of the tag.
pub struct Tag(Tag);
/// Game badge.
pub struct Badge(Badge);
}
#[str(newtype, copy)]
pub struct Genre(pub slug::LowerSlug<15>);
/// Estimated time to read.
#[int(u8, 0..=100)]
pub enum TimeToReadHours {}

26
core/src/types/mark.rs Normal file
View file

@ -0,0 +1,26 @@
use eva::{array, data, str};
use crate::types::{entity, slug};
#[data]
#[derive(Default)]
pub struct Tags(pub array::ImmutableHeap<Tag, 64>);
#[data]
#[derive(Default)]
pub struct Genres(pub array::ImmutableHeap<Genre, 64>);
#[data]
#[derive(Default)]
pub struct Badges(pub array::ImmutableHeap<Badge, 64>);
#[str(newtype, copy)]
pub struct Genre(pub slug::LowerSlug<15>);
entity::define_eid! {
/// ID of the tag.
pub struct Tag(Tag);
/// Game badge.
pub struct Badge(Badge);
}

View file

@ -6,6 +6,8 @@ pub mod board;
pub mod message;
pub mod thread;
pub mod mark;
pub mod author;
pub mod user;

View file

@ -57,6 +57,8 @@ impl Games for HttpClient {
slug,
vndb,
release_date,
tags,
genres,
}| {
(
"/games".into(),
@ -65,6 +67,8 @@ impl Games for HttpClient {
description,
thumbnail,
author,
tags,
genres,
slug,
vndb,
release_date,

View file

@ -5,7 +5,7 @@ use crate::requests::status_code;
use viendesu_core::{
errors,
requests::games as reqs,
types::{Patch, author, file, game},
types::{Patch, author, file, game, mark},
};
#[data]
@ -15,9 +15,9 @@ pub struct Update {
pub description: Patch<Option<game::Description>>,
pub slug: Patch<game::Slug>,
pub thumbnail: Patch<Option<file::Id>>,
pub genres: Patch<game::Genres>,
pub badges: Patch<game::Badges>,
pub tags: Patch<game::Tags>,
pub genres: Patch<mark::Genres>,
pub badges: Patch<mark::Badges>,
pub tags: Patch<mark::Tags>,
pub screenshots: Patch<game::Screenshots>,
pub published: Patch<bool>,
}
@ -25,7 +25,7 @@ pub struct Update {
impl_req!(Update => [reqs::update::Ok; reqs::update::Err]);
status_code::direct!(reqs::update::Ok => OK);
status_code::map!(reqs::update::Err => [NotFound]);
status_code::map!(reqs::update::Err => [NotFound, NoSuchBadge, NoSuchGenre, NoSuchTag]);
#[data]
pub struct Search {
@ -62,6 +62,10 @@ pub struct Create {
pub thumbnail: Option<file::Id>,
pub author: author::Id,
pub slug: Option<game::Slug>,
#[serde(default)]
pub tags: mark::Tags,
#[serde(default)]
pub genres: mark::Genres,
pub vndb: Option<game::VndbId>,
pub release_date: Option<game::ReleaseDate>,
}
@ -69,7 +73,7 @@ pub struct Create {
impl_req!(Create => [reqs::create::Ok; reqs::create::Err]);
status_code::direct!(reqs::create::Ok => CREATED);
status_code::map!(reqs::create::Err => [AlreadyTaken, NoSuchAuthor]);
status_code::map!(reqs::create::Err => [AlreadyTaken, NoSuchAuthor, NoSuchGenre, NoSuchTag]);
const _: () = {
use errors::games::*;

View file

@ -46,3 +46,13 @@ pub struct ListBadges {
impl_req!(ListBadges => [reqs::list_badges::Ok; reqs::list_badges::Err]);
status_code::direct!(reqs::list_badges::Ok => OK);
status_code::map!(reqs::list_badges::Err => []);
const _: () = {
use viendesu_core::errors::marks::*;
use status_code::*;
direct!(NoSuchTag => NOT_FOUND);
direct!(NoSuchGenre => NOT_FOUND);
direct!(NoSuchBadge => NOT_FOUND);
};

View file

@ -350,6 +350,8 @@ fn games<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
title,
description,
thumbnail,
tags,
genres,
author,
slug,
vndb,
@ -364,6 +366,8 @@ fn games<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
thumbnail,
author,
slug,
tags,
genres,
vndb,
release_date,
})