1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use {
crate::{
semver_range::SemverRange,
specifier::{workspace_specifier::WorkspaceSpecifier, Specifier},
},
std::rc::Rc,
};
#[derive(Debug, PartialEq)]
pub struct WorkspaceProtocol {
/// The complete raw string
///
/// Examples:
/// - "workspace:^"
/// - "workspace:*"
/// - "workspace:1.2.3"
pub raw: String,
/// The version part after "workspace:"
///
/// Examples:
/// - "^"
/// - "*"
/// - "1.2.3"
pub version_str: String,
/// Cached inner specifier for delegation
///
/// Examples:
/// - "workspace:^" -> RangeOnly(SemverRange::Minor)
/// - "workspace:~" -> RangeOnly(SemverRange::Patch)
/// - "workspace:*" -> RangeOnly(SemverRange::Any)
/// - "workspace:1.2.3" -> Resolved(Exact("1.2.3"))
pub inner_specifier: WorkspaceSpecifier,
}
impl WorkspaceProtocol {
/// Create a new WorkspaceProtocol from a raw string
pub fn new(raw: String) -> Option<Self> {
let version_str = raw.strip_prefix("workspace:")?.to_string();
// Check for symbolic workspace references that need resolution
let inner_specifier = match version_str.as_str() {
"*" => WorkspaceSpecifier::RangeOnly(SemverRange::Any),
"^" => WorkspaceSpecifier::RangeOnly(SemverRange::Minor),
"~" => WorkspaceSpecifier::RangeOnly(SemverRange::Patch),
_ => {
// Try to parse as complete specifier (e.g., "1.2.3", "^1.2.3")
// Use create() instead of new() to avoid nested RefCell borrow
let spec = Rc::new(Specifier::create(&version_str));
WorkspaceSpecifier::Resolved(spec)
}
};
Some(Self {
raw,
version_str,
inner_specifier,
})
}
/// Create a WorkspaceProtocol as Specifier variant (for compatibility)
pub fn create(raw: &str) -> Specifier {
// This is the old API - just delegate to new and wrap
match Self::new(raw.to_string()) {
Some(wp) => Specifier::WorkspaceProtocol(wp),
None => Specifier::Unsupported(raw.to_string()),
}
}
/// Check if this workspace protocol needs resolution
pub fn needs_resolution(&self) -> bool {
self.inner_specifier.needs_resolution()
}
/// Get the resolved specifier if available
pub fn as_resolved(&self) -> Option<&Rc<Specifier>> {
self.inner_specifier.as_resolved()
}
}