kinode_process_lib/types/
process_id.rs1pub use crate::ProcessId;
2use serde::{Deserialize, Serialize};
3use std::hash::{Hash, Hasher};
4
5impl ProcessId {
9 pub fn new(process_name: Option<&str>, package_name: &str, publisher_node: &str) -> Self {
12 ProcessId {
13 process_name: process_name
14 .unwrap_or(&rand::random::<u64>().to_string())
15 .into(),
16 package_name: package_name.into(),
17 publisher_node: publisher_node.into(),
18 }
19 }
20 pub fn process(&self) -> &str {
22 &self.process_name
23 }
24 pub fn package(&self) -> &str {
26 &self.package_name
27 }
28 pub fn publisher(&self) -> &str {
33 &self.publisher_node
34 }
35}
36
37impl std::str::FromStr for ProcessId {
38 type Err = ProcessIdParseError;
39 fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
42 let re = regex::Regex::new(r"^[a-z0-9-]+:[a-z0-9-]+:[a-z0-9-.]+$").unwrap();
43 if !re.is_match(input) {
44 return Err(ProcessIdParseError::InvalidCharacter);
45 }
46
47 let segments: Vec<&str> = input.split(':').collect();
48 Ok(ProcessId {
49 process_name: segments[0].to_string(),
50 package_name: segments[1].to_string(),
51 publisher_node: segments[2].to_string(),
52 })
53 }
54}
55
56impl Serialize for ProcessId {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: serde::ser::Serializer,
60 {
61 format!("{}", self).serialize(serializer)
62 }
63}
64
65impl<'a> Deserialize<'a> for ProcessId {
66 fn deserialize<D>(deserializer: D) -> Result<ProcessId, D::Error>
67 where
68 D: serde::de::Deserializer<'a>,
69 {
70 let s = String::deserialize(deserializer)?;
71 s.parse().map_err(serde::de::Error::custom)
72 }
73}
74
75impl Hash for ProcessId {
76 fn hash<H: Hasher>(&self, state: &mut H) {
77 self.process_name.hash(state);
78 self.package_name.hash(state);
79 self.publisher_node.hash(state);
80 }
81}
82
83impl Eq for ProcessId {}
84
85impl From<(&str, &str, &str)> for ProcessId {
86 fn from(input: (&str, &str, &str)) -> Self {
87 ProcessId::new(Some(input.0), input.1, input.2)
88 }
89}
90
91impl std::fmt::Display for ProcessId {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 write!(
94 f,
95 "{}:{}:{}",
96 self.process_name, self.package_name, self.publisher_node
97 )
98 }
99}
100
101impl PartialEq for ProcessId {
102 fn eq(&self, other: &Self) -> bool {
103 self.process_name == other.process_name
104 && self.package_name == other.package_name
105 && self.publisher_node == other.publisher_node
106 }
107}
108
109impl PartialEq<&str> for ProcessId {
110 fn eq(&self, other: &&str) -> bool {
111 &self.to_string() == other
112 }
113}
114
115impl PartialEq<ProcessId> for &str {
116 fn eq(&self, other: &ProcessId) -> bool {
117 self == &other.to_string()
118 }
119}
120
121#[derive(Debug)]
122pub enum ProcessIdParseError {
123 TooManyColons,
124 MissingField,
125 InvalidCharacter,
126}
127
128impl std::fmt::Display for ProcessIdParseError {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 write!(
131 f,
132 "{}",
133 match self {
134 ProcessIdParseError::TooManyColons => "Too many colons",
135 ProcessIdParseError::MissingField => "Missing field",
136 ProcessIdParseError::InvalidCharacter => "Invalid character",
137 }
138 )
139 }
140}
141
142impl std::error::Error for ProcessIdParseError {
143 fn description(&self) -> &str {
144 match self {
145 ProcessIdParseError::TooManyColons => "Too many colons",
146 ProcessIdParseError::MissingField => "Missing field",
147 ProcessIdParseError::InvalidCharacter => "Invalid character",
148 }
149 }
150}