Skip to content

Commit f46fa23

Browse files
committed
perf(specifier): lazily create node_[range|version]
1 parent 51583aa commit f46fa23

File tree

7 files changed

+217
-216
lines changed

7 files changed

+217
-216
lines changed
Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
11
use {
2-
crate::{semver_range::SemverRange, Specifier},
3-
std::rc::Rc,
2+
crate::{semver_range::SemverRange, Specifier, HUGE},
3+
std::{cell::OnceCell, rc::Rc},
44
};
55

6-
#[derive(Debug, PartialEq)]
6+
#[derive(Debug)]
77
pub struct Latest {
8-
/// "*"
9-
/// "latest"
10-
/// "x"
8+
/// "*", "latest", "x"
119
pub raw: String,
12-
/// Used for ordering - Latest gets the HUGE version (999999.999999.999999)
13-
/// so it sorts after all real versions
14-
pub node_version: Rc<node_semver::Version>,
10+
/// Lazily parsed HUGE version for ordering (999999.999999.999999)
11+
node_version: OnceCell<Rc<node_semver::Version>>,
1512
/// The semver range is always Any for Latest
1613
pub semver_range: SemverRange,
1714
}
1815

16+
impl PartialEq for Latest {
17+
fn eq(&self, other: &Self) -> bool {
18+
self.raw == other.raw && self.semver_range == other.semver_range
19+
}
20+
}
21+
1922
impl Latest {
2023
pub fn create(raw: &str) -> Specifier {
21-
let huge = crate::HUGE.to_string();
22-
let huge_version = format!("{huge}.{huge}.{huge}");
23-
match Specifier::new_node_version(&huge_version) {
24-
Some(node_version) => Specifier::Latest(Self {
25-
raw: raw.to_string(),
26-
node_version,
27-
semver_range: SemverRange::Any,
28-
}),
29-
None => Specifier::Unsupported(raw.to_string()),
24+
Specifier::Latest(Self {
25+
raw: raw.to_string(),
26+
node_version: OnceCell::new(),
27+
semver_range: SemverRange::Any,
28+
})
29+
}
30+
31+
#[cfg(test)]
32+
pub fn create_test(raw: &str) -> Self {
33+
Self {
34+
raw: raw.to_string(),
35+
node_version: OnceCell::new(),
36+
semver_range: SemverRange::Any,
3037
}
3138
}
39+
40+
pub fn get_node_version(&self) -> Rc<node_semver::Version> {
41+
self
42+
.node_version
43+
.get_or_init(|| {
44+
let huge = HUGE.to_string();
45+
let huge_version = format!("{huge}.{huge}.{huge}");
46+
Specifier::new_node_version(&huge_version).expect("HUGE version is always valid")
47+
})
48+
.clone()
49+
}
3250
}

crates/syncpack-specifier/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,12 @@ impl Specifier {
387387
Self::Alias(s) => s.inner_specifier.get_node_version(),
388388
Self::Git(s) => s.node_version.clone(),
389389
Self::Exact(s) => Some(s.node_version.clone()),
390-
Self::Latest(s) => Some(s.node_version.clone()),
391-
Self::Major(s) => Some(s.node_version.clone()),
392-
Self::Minor(s) => Some(s.node_version.clone()),
390+
Self::Latest(s) => Some(s.get_node_version()),
391+
Self::Major(s) => Some(s.get_node_version()),
392+
Self::Minor(s) => Some(s.get_node_version()),
393393
Self::Range(s) => Some(s.node_version.clone()),
394-
Self::RangeMajor(s) => Some(s.node_version.clone()),
395-
Self::RangeMinor(s) => Some(s.node_version.clone()),
394+
Self::RangeMajor(s) => Some(s.get_node_version()),
395+
Self::RangeMinor(s) => Some(s.get_node_version()),
396396
Self::WorkspaceProtocol(s) => s.as_resolved().and_then(|spec: &Rc<Specifier>| spec.get_node_version()),
397397
Self::Catalog(_)
398398
| Self::ComplexSemver(_)
@@ -418,8 +418,8 @@ impl Specifier {
418418
Self::ComplexSemver(s) => Some(s.node_range.clone()),
419419
Self::Git(s) => s.node_range.clone(),
420420
Self::Range(s) => Some(s.node_range.clone()),
421-
Self::RangeMajor(s) => Some(s.node_range.clone()),
422-
Self::RangeMinor(s) => Some(s.node_range.clone()),
421+
Self::RangeMajor(s) => Some(s.get_node_range()),
422+
Self::RangeMinor(s) => Some(s.get_node_range()),
423423
Self::WorkspaceProtocol(s) => {
424424
// Try resolved specifier first, otherwise check for "*" (RangeOnly(Any))
425425
s.as_resolved().and_then(|spec: &Rc<Specifier>| spec.get_node_range()).or_else(|| {
Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,45 @@
11
use {
22
crate::{Specifier, HUGE},
3-
std::rc::Rc,
3+
std::{cell::OnceCell, rc::Rc},
44
};
55

6-
#[derive(Debug, PartialEq)]
6+
#[derive(Debug)]
77
pub struct Major {
88
/// "1"
99
pub raw: String,
10-
/// Used for ordering and comparison
11-
///
12-
/// "1" -> "1.999999.999999"
13-
pub node_version: Rc<node_semver::Version>,
10+
/// Lazily parsed padded version: "1" -> "1.999999.999999"
11+
node_version: OnceCell<Rc<node_semver::Version>>,
12+
}
13+
14+
impl PartialEq for Major {
15+
fn eq(&self, other: &Self) -> bool {
16+
self.raw == other.raw
17+
}
1418
}
1519

1620
impl Major {
1721
pub fn create(raw: &str) -> Specifier {
18-
let padded = format!("{}.{}.{}", raw, HUGE, HUGE);
19-
match Specifier::new_node_version(&padded) {
20-
Some(node_version) => Specifier::Major(Self {
21-
raw: raw.to_string(),
22-
node_version,
23-
}),
24-
None => Specifier::Unsupported(raw.to_string()),
22+
Specifier::Major(Self {
23+
raw: raw.to_string(),
24+
node_version: OnceCell::new(),
25+
})
26+
}
27+
28+
#[cfg(test)]
29+
pub fn create_test(raw: &str) -> Self {
30+
Self {
31+
raw: raw.to_string(),
32+
node_version: OnceCell::new(),
2533
}
2634
}
35+
36+
pub fn get_node_version(&self) -> Rc<node_semver::Version> {
37+
self
38+
.node_version
39+
.get_or_init(|| {
40+
let padded = format!("{}.{}.{}", self.raw, HUGE, HUGE);
41+
Specifier::new_node_version(&padded).expect("pre-validated major version")
42+
})
43+
.clone()
44+
}
2745
}
Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,45 @@
11
use {
22
crate::{Specifier, HUGE},
3-
std::rc::Rc,
3+
std::{cell::OnceCell, rc::Rc},
44
};
55

6-
#[derive(Debug, PartialEq)]
6+
#[derive(Debug)]
77
pub struct Minor {
88
/// "1.2"
99
pub raw: String,
10-
/// Used for ordering and comparison
11-
///
12-
/// "1.2" -> "1.2.999999"
13-
pub node_version: Rc<node_semver::Version>,
10+
/// Lazily parsed padded version: "1.2" -> "1.2.999999"
11+
node_version: OnceCell<Rc<node_semver::Version>>,
12+
}
13+
14+
impl PartialEq for Minor {
15+
fn eq(&self, other: &Self) -> bool {
16+
self.raw == other.raw
17+
}
1418
}
1519

1620
impl Minor {
1721
pub fn create(raw: &str) -> Specifier {
18-
let padded = format!("{}.{}", raw, HUGE);
19-
match Specifier::new_node_version(&padded) {
20-
Some(node_version) => Specifier::Minor(Self {
21-
raw: raw.to_string(),
22-
node_version,
23-
}),
24-
None => Specifier::Unsupported(raw.to_string()),
22+
Specifier::Minor(Self {
23+
raw: raw.to_string(),
24+
node_version: OnceCell::new(),
25+
})
26+
}
27+
28+
#[cfg(test)]
29+
pub fn create_test(raw: &str) -> Self {
30+
Self {
31+
raw: raw.to_string(),
32+
node_version: OnceCell::new(),
2533
}
2634
}
35+
36+
pub fn get_node_version(&self) -> Rc<node_semver::Version> {
37+
self
38+
.node_version
39+
.get_or_init(|| {
40+
let padded = format!("{}.{}", self.raw, HUGE);
41+
Specifier::new_node_version(&padded).expect("pre-validated minor version")
42+
})
43+
.clone()
44+
}
2745
}
Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,72 @@
11
use {
22
crate::{semver_range::SemverRange, strip_semver_range, Specifier, HUGE},
3-
std::rc::Rc,
3+
std::{cell::OnceCell, rc::Rc},
44
};
55

6-
#[derive(Debug, PartialEq)]
6+
#[derive(Debug)]
77
pub struct RangeMajor {
88
/// "^1"
99
pub raw: String,
10-
/// Used when checking if specifiers satisfy each other
11-
///
12-
/// - "^1.999999.999999"
13-
pub node_range: Rc<node_semver::Range>,
14-
/// Used for ordering and comparison, semver range characters are NOT
15-
/// included
16-
///
17-
/// - "^1" → "1.999999.999999"
18-
pub node_version: Rc<node_semver::Version>,
19-
/// The raw semver specifier without range characters
20-
///
21-
/// "1"
10+
/// Lazily parsed range: "^1.999999.999999"
11+
node_range: OnceCell<Rc<node_semver::Range>>,
12+
/// Lazily parsed padded version: "1.999999.999999"
13+
node_version: OnceCell<Rc<node_semver::Version>>,
14+
/// The raw semver specifier without range characters: "1"
2215
pub semver_number: String,
2316
/// The semver range characters used in this specifier
24-
///
25-
/// `SemverRange::Minor`
2617
pub semver_range: SemverRange,
2718
}
2819

20+
impl PartialEq for RangeMajor {
21+
fn eq(&self, other: &Self) -> bool {
22+
self.raw == other.raw
23+
}
24+
}
25+
2926
impl RangeMajor {
3027
pub fn create(raw: &str) -> Specifier {
3128
let semver_range = SemverRange::parse(raw);
3229
let semver_number = strip_semver_range(raw).to_string();
33-
let padded = format!("{}.{}.{}", semver_number, HUGE, HUGE);
34-
let range_str = format!("{}{}", semver_range.unwrap(), padded);
30+
Specifier::RangeMajor(Self {
31+
raw: raw.to_string(),
32+
node_range: OnceCell::new(),
33+
node_version: OnceCell::new(),
34+
semver_number,
35+
semver_range,
36+
})
37+
}
3538

36-
match (Specifier::new_node_version(&padded), Specifier::new_node_range(&range_str)) {
37-
(Some(node_version), Some(node_range)) => Specifier::RangeMajor(Self {
38-
raw: raw.to_string(),
39-
node_range,
40-
node_version,
41-
semver_number,
42-
semver_range,
43-
}),
44-
_ => Specifier::Unsupported(raw.to_string()),
39+
#[cfg(test)]
40+
pub fn create_test(raw: &str) -> Self {
41+
let semver_range = SemverRange::parse(raw);
42+
let semver_number = strip_semver_range(raw).to_string();
43+
Self {
44+
raw: raw.to_string(),
45+
node_range: OnceCell::new(),
46+
node_version: OnceCell::new(),
47+
semver_number,
48+
semver_range,
4549
}
4650
}
51+
52+
pub fn get_node_version(&self) -> Rc<node_semver::Version> {
53+
self
54+
.node_version
55+
.get_or_init(|| {
56+
let padded = format!("{}.{}.{}", self.semver_number, HUGE, HUGE);
57+
Specifier::new_node_version(&padded).expect("pre-validated range major version")
58+
})
59+
.clone()
60+
}
61+
62+
pub fn get_node_range(&self) -> Rc<node_semver::Range> {
63+
self
64+
.node_range
65+
.get_or_init(|| {
66+
let padded = format!("{}.{}.{}", self.semver_number, HUGE, HUGE);
67+
let range_str = format!("{}{}", self.semver_range.unwrap(), padded);
68+
Specifier::new_node_range(&range_str).expect("pre-validated range major")
69+
})
70+
.clone()
71+
}
4772
}

0 commit comments

Comments
 (0)