1use super::{QueryField, SortQueryBy};
2use crate::{impl_id_newtype, impl_into_field_set};
3use regex::Regex;
4use serde::{Deserialize, Serialize};
5use std::sync::{Arc, LazyLock};
6use strum::{Display, EnumString, VariantArray};
7
8static ID_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^i\d+$").unwrap());
9
10#[remain::sorted]
11#[derive(Clone, Debug, Deserialize, Serialize)]
12#[cfg_attr(feature = "specta", derive(specta::Type))]
13pub struct Trait {
14 pub aliases: Option<Vec<String>>,
15 pub applicable: Option<bool>,
16 pub char_count: Option<u32>,
17 pub description: Option<String>,
18 pub group_id: Option<TraitId>,
19 pub group_name: Option<String>,
20 pub id: TraitId,
21 pub name: Option<String>,
22 pub searchable: Option<bool>,
23 pub sexual: Option<bool>,
24}
25
26impl From<Trait> for TraitId {
27 fn from(t: Trait) -> Self {
28 t.id
29 }
30}
31
32#[derive(
33 Debug,
34 Deserialize,
35 Serialize,
36 PartialEq,
37 Eq,
38 PartialOrd,
39 Ord,
40 Hash,
41 derive_more::Display,
42 derive_more::Into,
43)]
44#[cfg_attr(feature = "specta", derive(specta::Type))]
45pub struct TraitId(#[cfg_attr(feature = "specta", specta(type = String))] Arc<str>);
46
47impl TraitId {
48 pub const PREFIX: char = 'i';
49}
50
51impl_id_newtype!(Trait, TraitId, ID_REGEX);
52
53#[non_exhaustive]
54#[remain::sorted]
55#[derive(Clone, Copy, Debug, Deserialize, Serialize, Display, EnumString, VariantArray)]
56#[cfg_attr(feature = "specta", derive(specta::Type))]
57pub enum TraitField {
58 #[serde(rename = "aliases")]
59 #[strum(serialize = "aliases")]
60 Aliases,
61
62 #[serde(rename = "applicable")]
63 #[strum(serialize = "applicable")]
64 Applicable,
65
66 #[serde(rename = "char_count")]
67 #[strum(serialize = "char_count")]
68 CharCount,
69
70 #[serde(rename = "description")]
71 #[strum(serialize = "description")]
72 Description,
73
74 #[serde(rename = "group_id")]
75 #[strum(serialize = "group_id")]
76 GroupId,
77
78 #[serde(rename = "group_name")]
79 #[strum(serialize = "group_name")]
80 GroupName,
81
82 #[serde(rename = "id")]
83 #[strum(serialize = "id")]
84 Id,
85
86 #[serde(rename = "name")]
87 #[strum(serialize = "name")]
88 Name,
89
90 #[serde(rename = "searchable")]
91 #[strum(serialize = "searchable")]
92 Searchable,
93
94 #[serde(rename = "sexual")]
95 #[strum(serialize = "sexual")]
96 Sexual,
97}
98
99impl QueryField for TraitField {}
100
101impl_into_field_set!(TraitField);
102
103#[non_exhaustive]
104#[remain::sorted]
105#[derive(Clone, Copy, Debug, Deserialize, Serialize, Display, EnumString)]
106#[cfg_attr(feature = "specta", derive(specta::Type))]
107pub enum SortTraitBy {
108 #[serde(rename = "char_count")]
109 #[strum(serialize = "char_count")]
110 CharCount,
111
112 #[serde(rename = "id")]
113 #[strum(serialize = "id")]
114 Id,
115
116 #[serde(rename = "name")]
117 #[strum(serialize = "name")]
118 Name,
119
120 #[serde(rename = "searchrank")]
121 #[strum(serialize = "searchrank")]
122 SearchRank,
123}
124
125impl SortQueryBy for SortTraitBy {}