mdbook_plotly/preprocessor/handlers/code_handler/
until.rs1use anyhow::{Result, anyhow};
2use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeOwned};
3use serde_json::{Map as JsonMap, Value, value::Index};
4use std::fmt::{Debug, Display};
5
6pub type Map = JsonMap<String, Value>;
7
8#[inline]
9pub fn must_translate<T, N>(obj: &mut Value, map: &Map, name: N) -> Result<T>
10where
11 T: DeserializeOwned + Serialize + Debug + Clone,
12 N: Index + Display,
13{
14 let result = obj
15 .get_mut(&name)
16 .ok_or(anyhow!("missing `{}` field", name))?;
17 let result = serde_json::from_value::<DataPack<T>>(result.take())?.unwrap(map)?;
18 Ok(result)
19}
20
21#[derive(Clone, Debug)]
22pub enum DataPack<T> {
23 Data(T),
24 Index(String),
25}
26
27impl<T> DataPack<T>
28where
29 T: DeserializeOwned + Serialize + Debug + Clone,
30{
31 pub fn unwrap(self, map: &Map) -> Result<T> {
32 let result = match self {
33 Self::Data(data) => data,
34 Self::Index(index) => {
35 let value = map
36 .get(&index)
37 .ok_or_else(|| anyhow!("Invalid index: {}", &index))?;
38 serde_json::from_value::<T>(value.clone())?
39 }
40 };
41 Ok(result)
42 }
43}
44
45impl<'de, T> Deserialize<'de> for DataPack<T>
46where
47 T: DeserializeOwned + Serialize + Debug + Clone,
48{
49 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
50 where
51 D: Deserializer<'de>,
52 {
53 let value = Value::deserialize(deserializer)?;
54 if let Value::String(ref s) = value
55 && let Some(idx) = s.strip_prefix("map.")
56 {
57 return Ok(DataPack::Index(idx.to_string()));
58 }
59 serde_json::from_value::<T>(value)
60 .map(DataPack::Data)
61 .map_err(serde::de::Error::custom)
62 }
63}
64
65impl<T> Serialize for DataPack<T>
66where
67 T: DeserializeOwned + Serialize + Debug + Clone,
68{
69 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70 where
71 S: Serializer,
72 {
73 match self {
74 Self::Data(data) => data.serialize(serializer),
75 Self::Index(index) => serializer.serialize_str(&format!("map.{index}")),
76 }
77 }
78}
79
80use plotly::color;
81
82#[allow(clippy::enum_variant_names)]
84#[derive(Clone, Debug, Serialize, Deserialize)]
85#[serde(rename_all = "snake_case")]
86pub enum Color {
87 NamedColor(color::NamedColor),
88 RgbColor(color::Rgb),
89 RgbaColor(color::Rgba),
90}
91
92impl color::Color for Color {}