1use std::borrow::Cow;
2
3use ordered_float::OrderedFloat;
4use serde::{Deserialize, Serialize, de};
5
6use crate::{Id, SStr, path::PathBufDyn, url::UrlBuf};
7
8#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
9#[serde(untagged)]
10pub enum DataKey {
11 Nil,
12 Boolean(bool),
13 #[serde(deserialize_with = "Self::deserialize_integer")]
14 Integer(i64),
15 Number(OrderedFloat<f64>),
16 String(SStr),
17 Id(Id),
18 #[serde(skip_deserializing)]
19 Url(UrlBuf),
20 #[serde(skip)]
21 Path(PathBufDyn),
22 #[serde(skip)]
23 Bytes(Vec<u8>),
24}
25
26impl DataKey {
27 pub fn is_integer(&self) -> bool { matches!(self, Self::Integer(_)) }
28
29 pub fn as_str(&self) -> Option<&str> {
30 match self {
31 Self::String(s) => Some(s),
32 _ => None,
33 }
34 }
35
36 fn deserialize_integer<'de, D>(deserializer: D) -> Result<i64, D::Error>
37 where
38 D: de::Deserializer<'de>,
39 {
40 struct Visitor;
41
42 impl de::Visitor<'_> for Visitor {
43 type Value = i64;
44
45 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
46 formatter.write_str("an integer or a string of an integer")
47 }
48
49 fn visit_i64<E>(self, value: i64) -> Result<i64, E> { Ok(value) }
50
51 fn visit_str<E>(self, value: &str) -> Result<i64, E>
52 where
53 E: de::Error,
54 {
55 value.parse().map_err(de::Error::custom)
56 }
57 }
58
59 deserializer.deserialize_any(Visitor)
60 }
61}
62
63impl From<usize> for DataKey {
64 fn from(value: usize) -> Self { Self::Integer(value as i64) }
65}
66
67impl From<&'static str> for DataKey {
68 fn from(value: &'static str) -> Self { Self::String(Cow::Borrowed(value)) }
69}
70
71impl From<String> for DataKey {
72 fn from(value: String) -> Self { Self::String(Cow::Owned(value)) }
73}
74
75impl_into_integer!(DataKey, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, crate::Id);
76impl_into_number!(DataKey, f32, f64);