Skip to content

Commit 78d0c1e

Browse files
committed
use regex to parse process/package
1 parent d6a7323 commit 78d0c1e

File tree

4 files changed

+23
-40
lines changed

4 files changed

+23
-40
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mime_guess = "2.0"
2727
serde = { version = "1.0", features = ["derive"] }
2828
serde_json = "1.0.120"
2929
rand = "0.8"
30+
regex = "1.11.1"
3031
rmp-serde = "1.1.2"
3132
thiserror = "1.0"
3233
tracing = { version = "0.1", optional = true }

src/types/package_id.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -129,28 +129,18 @@ impl<'de> Deserialize<'de> for PackageId {
129129

130130
impl std::str::FromStr for PackageId {
131131
type Err = ProcessIdParseError;
132-
/// Attempt to parse a `PackageId` from a string. The string must
133-
/// contain exactly two segments, where segments are non-empty strings
134-
/// separated by a colon (`:`). The segments cannot themselves contain colons.
132+
/// Attempts to parse a `PackageId` from a string. The string must match the pattern
133+
/// of two segments containing only lowercase letters, numbers and hyphens, separated by a colon.
135134
fn from_str(input: &str) -> Result<Self, Self::Err> {
136-
let segments: Vec<&str> = input.split(':').collect();
137-
if segments.len() < 2 {
138-
return Err(ProcessIdParseError::MissingField);
139-
} else if segments.len() > 2 {
140-
return Err(ProcessIdParseError::TooManyColons);
141-
}
142-
let package_name = segments[0].to_string();
143-
if package_name.is_empty() {
144-
return Err(ProcessIdParseError::MissingField);
145-
}
146-
let publisher_node = segments[1].to_string();
147-
if publisher_node.is_empty() {
148-
return Err(ProcessIdParseError::MissingField);
135+
let re = regex::Regex::new(r"^[a-z0-9-]+:[a-z0-9-]+$").unwrap();
136+
if !re.is_match(input) {
137+
return Err(ProcessIdParseError::InvalidCharacter);
149138
}
150139

140+
let segments: Vec<&str> = input.split(':').collect();
151141
Ok(PackageId {
152-
package_name,
153-
publisher_node,
142+
package_name: segments[0].to_string(),
143+
publisher_node: segments[1].to_string(),
154144
})
155145
}
156146
}

src/types/process_id.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,19 @@ impl ProcessId {
3636

3737
impl std::str::FromStr for ProcessId {
3838
type Err = ProcessIdParseError;
39-
/// Attempts to parse a `ProcessId` from a string. To succeed, the string must contain
40-
/// exactly 3 segments, separated by colons `:`. The segments must not contain colons.
39+
/// Attempts to parse a `ProcessId` from a string. The string must match the pattern
40+
/// of three segments containing only lowercase letters, numbers and hyphens, separated by colons.
4141
fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
42-
let segments: Vec<&str> = input.split(':').collect();
43-
if segments.len() < 3 {
44-
return Err(ProcessIdParseError::MissingField);
45-
} else if segments.len() > 3 {
46-
return Err(ProcessIdParseError::TooManyColons);
47-
}
48-
let process_name = segments[0].to_string();
49-
if process_name.is_empty() {
50-
return Err(ProcessIdParseError::MissingField);
51-
}
52-
let package_name = segments[1].to_string();
53-
if package_name.is_empty() {
54-
return Err(ProcessIdParseError::MissingField);
55-
}
56-
let publisher_node = segments[2].to_string();
57-
if publisher_node.is_empty() {
58-
return Err(ProcessIdParseError::MissingField);
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);
5945
}
46+
47+
let segments: Vec<&str> = input.split(':').collect();
6048
Ok(ProcessId {
61-
process_name,
62-
package_name,
63-
publisher_node,
49+
process_name: segments[0].to_string(),
50+
package_name: segments[1].to_string(),
51+
publisher_node: segments[2].to_string(),
6452
})
6553
}
6654
}
@@ -134,6 +122,7 @@ impl PartialEq<ProcessId> for &str {
134122
pub enum ProcessIdParseError {
135123
TooManyColons,
136124
MissingField,
125+
InvalidCharacter,
137126
}
138127

139128
impl std::fmt::Display for ProcessIdParseError {
@@ -144,6 +133,7 @@ impl std::fmt::Display for ProcessIdParseError {
144133
match self {
145134
ProcessIdParseError::TooManyColons => "Too many colons",
146135
ProcessIdParseError::MissingField => "Missing field",
136+
ProcessIdParseError::InvalidCharacter => "Invalid character",
147137
}
148138
)
149139
}
@@ -154,6 +144,7 @@ impl std::error::Error for ProcessIdParseError {
154144
match self {
155145
ProcessIdParseError::TooManyColons => "Too many colons",
156146
ProcessIdParseError::MissingField => "Missing field",
147+
ProcessIdParseError::InvalidCharacter => "Invalid character",
157148
}
158149
}
159150
}

0 commit comments

Comments
 (0)