1use serde::de::{self, Deserializer, MapAccess, Unexpected, Visitor};
2use serde::ser::{SerializeStruct, Serializer};
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone, Copy)]
7#[serde(rename_all = "snake_case")]
8pub enum ColorBy {
9 Series,
10 Data,
11}
12
13impl From<&str> for ColorBy {
14 fn from(s: &str) -> Self {
15 match s {
16 "series" => Self::Series,
17 "data" => Self::Data,
18 _ => panic!("Invalid ColorBy"),
19 }
20 }
21}
22
23#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone)]
24pub struct ColorStop {
25 offset: f64,
26 color: String,
27}
28
29impl ColorStop {
30 pub fn new<F: Into<f64>, S: Into<String>>(offset: F, color: S) -> Self {
31 Self {
32 offset: offset.into(),
33 color: color.into(),
34 }
35 }
36}
37
38#[derive(Debug, PartialEq, PartialOrd, Clone)]
39pub enum Color {
40 Value(String),
41 LinearGradient {
42 x: f64,
43 y: f64,
44 x2: f64,
45 y2: f64,
46 color_stops: Vec<ColorStop>,
47 },
48 RadialGradient {
49 x: f64,
50 y: f64,
51 r: f64,
52 color_stops: Vec<ColorStop>,
53 },
54}
55
56impl Serialize for Color {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: Serializer,
60 {
61 match self {
62 Color::Value(rgb) => serializer.serialize_str(rgb),
63 Color::LinearGradient {
64 x,
65 y,
66 x2,
67 y2,
68 color_stops,
69 } => {
70 let mut s = serializer.serialize_struct("LinearGradient", 5)?;
71 s.serialize_field("type", "linear")?;
72 s.serialize_field("x", x)?;
73 s.serialize_field("y", y)?;
74 s.serialize_field("x2", x2)?;
75 s.serialize_field("y2", y2)?;
76 s.serialize_field("colorStops", color_stops)?;
77 s.end()
78 }
79 Color::RadialGradient {
80 x,
81 y,
82 r,
83 color_stops,
84 } => {
85 let mut s = serializer.serialize_struct("RadialGradient", 4)?;
86 s.serialize_field("type", "radial")?;
87 s.serialize_field("x", x)?;
88 s.serialize_field("y", y)?;
89 s.serialize_field("r", r)?;
90 s.serialize_field("colorStops", color_stops)?;
91 s.end()
92 }
93 }
94 }
95}
96
97impl<'de> Deserialize<'de> for Color {
98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99 where
100 D: Deserializer<'de>,
101 {
102 struct ColorVisitor;
104
105 impl<'de> Visitor<'de> for ColorVisitor {
106 type Value = Color;
107
108 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
109 formatter.write_str("a string or a gradient object with type field")
110 }
111
112 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
113 where
114 E: de::Error,
115 {
116 Ok(Color::Value(value.to_string()))
117 }
118
119 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
120 where
121 M: MapAccess<'de>,
122 {
123 use serde_json::Value as JsonValue;
124
125 let mut temp_map = serde_json::Map::new();
127 let mut type_value = None;
128 while let Some((key, value)) = map.next_entry::<String, JsonValue>()? {
129 if key == "type" {
130 type_value = Some(value.clone())
131 }
132 temp_map.insert(key, value);
133 }
134
135 let type_value = type_value.ok_or_else(|| de::Error::missing_field("type"))?;
136
137 let type_value = type_value.as_str().ok_or_else(|| {
138 de::Error::invalid_type(Unexpected::Other("non-string"), &"a string")
139 })?;
140
141 let temp_value = JsonValue::Object(temp_map);
142
143 match type_value {
144 "linear" => {
145 #[derive(Deserialize)]
146 struct LinearGradientDef {
147 x: f64,
148 y: f64,
149 x2: f64,
150 y2: f64,
151 #[serde(rename = "colorStops")]
152 color_stops: Vec<ColorStop>,
153 }
154
155 let gradient: LinearGradientDef =
156 serde_json::from_value(temp_value).map_err(de::Error::custom)?;
157
158 Ok(Color::LinearGradient {
159 x: gradient.x,
160 y: gradient.y,
161 x2: gradient.x2,
162 y2: gradient.y2,
163 color_stops: gradient.color_stops,
164 })
165 }
166 "radial" => {
167 #[derive(Deserialize)]
168 struct RadialGradientDef {
169 x: f64,
170 y: f64,
171 r: f64,
172 #[serde(rename = "colorStops")]
173 color_stops: Vec<ColorStop>,
174 }
175
176 let gradient: RadialGradientDef =
177 serde_json::from_value(temp_value).map_err(de::Error::custom)?;
178
179 Ok(Color::RadialGradient {
180 x: gradient.x,
181 y: gradient.y,
182 r: gradient.r,
183 color_stops: gradient.color_stops,
184 })
185 }
186 other => Err(de::Error::unknown_variant(other, &["linear", "radial"])),
187 }
188 }
189 }
190
191 deserializer.deserialize_any(ColorVisitor)
192 }
193}
194
195impl From<&str> for Color {
196 fn from(s: &str) -> Self {
197 Color::Value(s.to_string())
198 }
199}
200
201impl From<String> for Color {
202 fn from(s: String) -> Self {
203 Color::Value(s)
204 }
205}