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 fn must_translate<T, N>(obj: &mut Value, name: N) -> Result<T>
7where
8    T: DeserializeOwned,
9    N: Index + Display,
10{
11    let result = obj
12        .get_mut(&name)
13        .ok_or(anyhow!("missing `{}` field", name))?;
14    let result = serde_json::from_value::<T>(result.take())?;
15    Ok(result)
16}
17
18pub type Map = JsonMap<String, Value>;
19
20#[derive(Clone, Debug)]
21pub enum DataPack<T>
22where
23    T: Debug + Clone,
24{
25    Data(T),
26    Index(String),
27}
28
29impl<T> DataPack<T>
30where
31    T: DeserializeOwned + Serialize + Debug + Clone,
32{
33    pub fn unwrap(self, map: &Map) -> Result<T> {
34        let result = match self {
35            Self::Data(data) => data,
36            Self::Index(index) => {
37                let value = map
38                    .get(&index)
39                    .ok_or_else(|| anyhow!("Invalid index: {}", &index))?;
40                serde_json::from_value::<T>(value.clone())?
41            }
42        };
43        Ok(result)
44    }
45}
46
47impl<'de, T> Deserialize<'de> for DataPack<T>
48where
49    T: DeserializeOwned + Serialize + Debug + Clone,
50{
51    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
52    where
53        D: Deserializer<'de>,
54    {
55        let value = Value::deserialize(deserializer)?;
56        if let Value::String(ref s) = value
57            && let Some(idx) = s.strip_prefix("map.")
58        {
59            return Ok(DataPack::Index(idx.to_string()));
60        }
61        serde_json::from_value::<T>(value)
62            .map(DataPack::Data)
63            .map_err(serde::de::Error::custom)
64    }
65}
66
67impl<T> Serialize for DataPack<T>
68where
69    T: DeserializeOwned + Serialize + Debug + Clone,
70{
71    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72    where
73        S: Serializer,
74    {
75        match self {
76            Self::Data(data) => data.serialize(serializer),
77            Self::Index(index) => serializer.serialize_str(&format!("map.{index}")),
78        }
79    }
80}