eva_common/value/
index.rs

1use crate::value::Value;
2use serde::{de, ser, ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
3
4#[derive(Debug, Clone, Eq, PartialEq, Hash)]
5pub struct Index(Vec<usize>);
6
7impl Index {
8    #[inline]
9    pub fn as_slice(&self) -> IndexSlice<'_> {
10        IndexSlice(&self.0)
11    }
12}
13
14impl<'de> Deserialize<'de> for Index {
15    #[inline]
16    fn deserialize<D>(deserializer: D) -> Result<Index, D::Error>
17    where
18        D: Deserializer<'de>,
19    {
20        let val: Value = Deserialize::deserialize(deserializer)?;
21        match val {
22            Value::String(s) => {
23                let mut res = Vec::new();
24                for v in s.split(',') {
25                    let i = v.parse::<usize>().map_err(de::Error::custom)?;
26                    res.push(i);
27                }
28                Ok(Index(res))
29            }
30            Value::Seq(s) => {
31                let mut res = Vec::with_capacity(s.len());
32                for v in s {
33                    let i = u64::try_from(v).map_err(de::Error::custom)?;
34                    let u = usize::try_from(i).map_err(de::Error::custom)?;
35                    res.push(u);
36                }
37                Ok(Index(res))
38            }
39            _ => {
40                if let Ok(v) = u64::try_from(val) {
41                    Ok(Index(vec![usize::try_from(v).map_err(de::Error::custom)?]))
42                } else {
43                    Err(de::Error::custom(
44                        "unsupported index (should be integer, list or string)",
45                    ))
46                }
47            }
48        }
49    }
50}
51
52impl Serialize for Index {
53    #[inline]
54    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55    where
56        S: Serializer,
57    {
58        if self.0.len() == 1 {
59            serializer.serialize_u64(u64::try_from(self.0[0]).map_err(ser::Error::custom)?)
60        } else {
61            let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
62            for idx in &self.0 {
63                seq.serialize_element(idx)?;
64            }
65            seq.end()
66        }
67    }
68}
69
70#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
71#[allow(clippy::module_name_repetitions)]
72pub struct IndexSlice<'a>(pub(crate) &'a [usize]);