1use core::fmt;
4use core::str::FromStr;
5
6use serde::{Deserialize, Serialize};
7
8pub const MAX_DEVICE_ID_LEN: usize = 64;
10
11#[derive(
23 Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, schemars::JsonSchema,
24)]
25#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
26#[serde(try_from = "String", into = "String")]
27pub struct DeviceId(String);
28
29impl DeviceId {
30 pub fn as_str(&self) -> &str {
32 &self.0
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq)]
38pub struct InvalidId {
39 pub(crate) what: &'static str,
40 pub(crate) value: String,
41}
42
43impl fmt::Display for InvalidId {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 write!(f, "invalid {}: {:?}", self.what, self.value)
46 }
47}
48
49impl std::error::Error for InvalidId {}
50
51impl FromStr for DeviceId {
52 type Err = InvalidId;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 let valid = !s.is_empty()
56 && s.len() <= MAX_DEVICE_ID_LEN
57 && s.bytes()
58 .all(|b| b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_' | b'.'));
59 if valid {
60 Ok(DeviceId(s.to_owned()))
61 } else {
62 Err(InvalidId {
63 what: "device id",
64 value: s.to_owned(),
65 })
66 }
67 }
68}
69
70impl TryFrom<String> for DeviceId {
71 type Error = InvalidId;
72
73 fn try_from(s: String) -> Result<Self, Self::Error> {
74 s.parse()
75 }
76}
77
78impl From<DeviceId> for String {
79 fn from(id: DeviceId) -> String {
80 id.0
81 }
82}
83
84impl fmt::Display for DeviceId {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 f.write_str(&self.0)
87 }
88}
89
90impl AsRef<str> for DeviceId {
91 fn as_ref(&self) -> &str {
92 &self.0
93 }
94}
95
96#[derive(
104 Clone,
105 Copy,
106 Debug,
107 Default,
108 PartialEq,
109 Eq,
110 PartialOrd,
111 Ord,
112 Hash,
113 Serialize,
114 Deserialize,
115 schemars::JsonSchema,
116)]
117#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
118#[serde(transparent)]
119pub struct JobId(pub u64);
120
121impl fmt::Display for JobId {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 write!(f, "{}", self.0)
124 }
125}