1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
15#[serde(deny_unknown_fields)]
16#[serde(untagged)]
17pub enum Id {
18 Num(u64),
20 Str(String),
22}
23
24impl Id {
25 pub fn as_number(&self) -> Option<&u64> {
28 match self {
29 Self::Num(id) => Some(id),
30 _ => None,
31 }
32 }
33
34 pub fn as_str(&self) -> Option<&str> {
37 match self {
38 Self::Str(id) => Some(id),
39 _ => None,
40 }
41 }
42}
43
44impl fmt::Display for Id {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 match self {
47 Self::Num(id) => write!(f, "{}", id),
48 Self::Str(id) => f.write_str(id),
49 }
50 }
51}
52
53impl From<u64> for Id {
54 fn from(id: u64) -> Self {
55 Self::Num(id)
56 }
57}
58
59impl From<String> for Id {
60 fn from(id: String) -> Self {
61 Self::Str(id)
62 }
63}
64
65impl From<Id> for Value {
66 fn from(id: Id) -> Self {
67 match id {
68 Id::Num(id) => Self::Number(id.into()),
69 Id::Str(id) => Self::String(id),
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn id_serialization() {
80 let cases = vec![
81 (Id::Num(0), r#"0"#),
82 (Id::Str("1".into()), r#""1""#),
83 (Id::Str("test".into()), r#""test""#),
84 ];
85
86 for (id, expect) in cases {
87 assert_eq!(serde_json::to_string(&id).unwrap(), expect);
88 assert_eq!(id, serde_json::from_str(expect).unwrap());
89 }
90
91 assert_eq!(
92 serde_json::to_string(&vec![Id::Num(0), Id::Str("1".to_owned()), Id::Str("test".to_owned()),]).unwrap(),
93 r#"[0,"1","test"]"#
94 );
95 }
96}