Skip to main content

mdbook_plotly/preprocessor/handlers/code_handler/
until.rs

1use 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// This is to make Json look clearer when it is written.
83#[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 {}