1pub mod base16;
2pub mod base24;
3mod color;
4pub mod tinted8;
5
6use serde::{Deserialize, Serialize};
7use std::{fmt, str::FromStr};
8
9pub use crate::scheme::color::Color;
10pub use crate::scheme::color::{ColorName, ColorType, ColorVariant};
11use crate::TintedBuilderError;
12
13#[non_exhaustive]
17#[derive(Debug, Clone)]
18pub enum Scheme {
19 Base16(base16::Scheme),
21 Base24(base24::Scheme),
23 Tinted8(Box<tinted8::Scheme>),
25}
26
27impl Scheme {
28 pub fn from_yaml(yaml: &str) -> Result<Self, TintedBuilderError> {
39 let raw: serde_yaml::Value =
40 serde_yaml::from_str(yaml).map_err(TintedBuilderError::YamlDeserialize)?;
41
42 let system = raw
43 .get("system")
44 .or_else(|| raw.get("scheme").and_then(|s| s.get("system")))
45 .and_then(serde_yaml::Value::as_str)
46 .ok_or_else(|| TintedBuilderError::SchemeMissingProperty("system".to_string()))?
47 .parse::<SchemeSystem>()?;
48
49 match system {
50 SchemeSystem::Base16 => {
51 let scheme: base16::Scheme =
52 serde_yaml::from_str(yaml).map_err(TintedBuilderError::YamlDeserialize)?;
53 Ok(Self::Base16(scheme))
54 }
55 SchemeSystem::Base24 => {
56 let scheme: base24::Scheme =
57 serde_yaml::from_str(yaml).map_err(TintedBuilderError::YamlDeserialize)?;
58 Ok(Self::Base24(scheme))
59 }
60 SchemeSystem::Tinted8 => {
61 let scheme: tinted8::Scheme =
62 serde_yaml::from_str(yaml).map_err(TintedBuilderError::YamlDeserialize)?;
63 Ok(Self::Tinted8(Box::new(scheme)))
64 }
65 }
66 }
67
68 #[must_use]
70 pub fn get_scheme_author(&self) -> String {
71 match self {
72 Self::Base16(scheme) => scheme.author.clone(),
73 Self::Base24(scheme) => scheme.author.clone(),
74 Self::Tinted8(scheme) => scheme.scheme.author.clone(),
75 }
76 }
77 #[must_use]
79 pub fn get_scheme_description(&self) -> String {
80 match self {
81 Self::Base16(scheme) => scheme.description.clone().unwrap_or_default(),
82 Self::Base24(scheme) => scheme.description.clone().unwrap_or_default(),
83 Self::Tinted8(scheme) => scheme.scheme.description.clone().unwrap_or_default(),
84 }
85 }
86 #[must_use]
88 pub fn get_scheme_name(&self) -> String {
89 match self {
90 Self::Base16(scheme) => scheme.name.clone(),
91 Self::Base24(scheme) => scheme.name.clone(),
92 Self::Tinted8(scheme) => scheme.scheme.name.clone(),
93 }
94 }
95 #[must_use]
97 pub fn get_scheme_slug(&self) -> String {
98 match self {
99 Self::Base16(scheme) => scheme.slug.clone(),
100 Self::Base24(scheme) => scheme.slug.clone(),
101 Self::Tinted8(scheme) => scheme.scheme.slug.clone(),
102 }
103 }
104 #[must_use]
106 pub const fn get_scheme_system(&self) -> SchemeSystem {
107 match self {
108 Self::Base16(_) => SchemeSystem::Base16,
109 Self::Base24(_) => SchemeSystem::Base24,
110 Self::Tinted8(_) => SchemeSystem::Tinted8,
111 }
112 }
113 #[must_use]
115 pub fn get_scheme_variant(&self) -> SchemeVariant {
116 match self {
117 Self::Base16(scheme) => scheme.variant.clone(),
118 Self::Base24(scheme) => scheme.variant.clone(),
119 Self::Tinted8(scheme) => scheme.variant.clone(),
120 }
121 }
122}
123
124#[non_exhaustive]
127#[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)]
128#[serde(rename_all = "lowercase")]
129pub enum SchemeSystem {
130 #[default]
132 Base16,
133 Base24,
135 Tinted8,
137}
138#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)]
139#[serde(rename_all = "lowercase")]
140pub struct SchemeSupports {
141 #[serde(rename = "styling-spec")]
142 pub styling_spec: String,
143}
144
145impl SchemeSystem {
146 #[must_use]
148 pub const fn as_str(&self) -> &str {
149 match self {
150 Self::Base16 => "base16",
151 Self::Base24 => "base24",
152 Self::Tinted8 => "tinted8",
153 }
154 }
155 #[must_use]
156 pub const fn variants() -> &'static [Self] {
157 &[Self::Base16, Self::Base24, Self::Tinted8]
158 }
159}
160
161impl fmt::Display for SchemeSystem {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 write!(f, "{}", self.as_str())?;
165 Ok(())
166 }
167}
168
169impl FromStr for SchemeSystem {
170 type Err = TintedBuilderError;
171
172 fn from_str(system_str: &str) -> Result<Self, Self::Err> {
179 match system_str {
180 "base16" => Ok(Self::Base16),
181 "base24" => Ok(Self::Base24),
182 "tinted8" => Ok(Self::Tinted8),
183 _ => Err(TintedBuilderError::InvalidSchemeSystem(
184 system_str.to_string(),
185 )),
186 }
187 }
188}
189
190#[non_exhaustive]
194#[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)]
195#[serde(rename_all = "lowercase")]
196pub enum SchemeVariant {
197 #[default]
199 Dark,
200 Light,
202}
203
204impl FromStr for SchemeVariant {
205 type Err = TintedBuilderError;
206
207 fn from_str(variant_str: &str) -> Result<Self, Self::Err> {
214 match variant_str {
215 "light" => Ok(Self::Light),
216 "dark" => Ok(Self::Dark),
217 _ => Err(TintedBuilderError::InvalidSchemeVariant(
218 variant_str.to_string(),
219 )),
220 }
221 }
222}
223
224impl SchemeVariant {
225 #[must_use]
227 pub const fn as_str(&self) -> &str {
228 match self {
229 Self::Dark => "dark",
230 Self::Light => "light",
231 }
232 }
233}
234
235impl fmt::Display for SchemeVariant {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
238 write!(f, "{}", self.as_str())?;
239 Ok(())
240 }
241}