Skip to content

Commit 113d4a6

Browse files
committed
feat: from and as RangeBounds
1 parent ca782bc commit 113d4a6

6 files changed

+116
-23
lines changed

examples/branching_error_reporting.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,31 @@ fn main() {
1313
// root 1.0.0 depends on foo ^1.0.0
1414
dependency_provider.add_dependencies(
1515
"root", (1, 0, 0),
16-
[("foo", Range::between((1, 0, 0), (2, 0, 0)))],
16+
[("foo", Range::from_range_bounds((1, 0, 0)..(2, 0, 0)))],
1717
);
1818
#[rustfmt::skip]
1919
// foo 1.0.0 depends on a ^1.0.0 and b ^1.0.0
2020
dependency_provider.add_dependencies(
2121
"foo", (1, 0, 0),
2222
[
23-
("a", Range::between((1, 0, 0), (2, 0, 0))),
24-
("b", Range::between((1, 0, 0), (2, 0, 0))),
23+
("a", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
24+
("b", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
2525
],
2626
);
2727
#[rustfmt::skip]
2828
// foo 1.1.0 depends on x ^1.0.0 and y ^1.0.0
2929
dependency_provider.add_dependencies(
3030
"foo", (1, 1, 0),
3131
[
32-
("x", Range::between((1, 0, 0), (2, 0, 0))),
33-
("y", Range::between((1, 0, 0), (2, 0, 0))),
32+
("x", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
33+
("y", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
3434
],
3535
);
3636
#[rustfmt::skip]
3737
// a 1.0.0 depends on b ^2.0.0
3838
dependency_provider.add_dependencies(
3939
"a", (1, 0, 0),
40-
[("b", Range::between((2, 0, 0), (3, 0, 0)))],
40+
[("b", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))],
4141
);
4242
// b 1.0.0 and 2.0.0 have no dependencies.
4343
dependency_provider.add_dependencies("b", (1, 0, 0), []);
@@ -46,7 +46,7 @@ fn main() {
4646
// x 1.0.0 depends on y ^2.0.0.
4747
dependency_provider.add_dependencies(
4848
"x", (1, 0, 0),
49-
[("y", Range::between((2, 0, 0), (3, 0, 0)))],
49+
[("y", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))],
5050
);
5151
// y 1.0.0 and 2.0.0 have no dependencies.
5252
dependency_provider.add_dependencies("y", (1, 0, 0), []);

examples/doc_interface_error.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ fn main() {
2525

2626
// Dependencies of the menu lib.
2727
dependency_provider.add_dependencies("menu", (1, 0, 0), [
28-
("dropdown", Range::strictly_lower_than((2, 0, 0))),
28+
("dropdown", Range::from_range_bounds(..(2, 0, 0))),
2929
]);
3030
dependency_provider.add_dependencies("menu", (1, 1, 0), [
31-
("dropdown", Range::higher_than((2, 0, 0))),
31+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3232
]);
3333
dependency_provider.add_dependencies("menu", (1, 2, 0), [
34-
("dropdown", Range::higher_than((2, 0, 0))),
34+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3535
]);
3636
dependency_provider.add_dependencies("menu", (1, 3, 0), [
37-
("dropdown", Range::higher_than((2, 0, 0))),
37+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3838
]);
3939
dependency_provider.add_dependencies("menu", (1, 4, 0), [
40-
("dropdown", Range::higher_than((2, 0, 0))),
40+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
4141
]);
4242
dependency_provider.add_dependencies("menu", (1, 5, 0), [
43-
("dropdown", Range::higher_than((2, 0, 0))),
43+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
4444
]);
4545

4646
// Dependencies of the dropdown lib.

examples/doc_interface_semantic.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,22 @@ fn main() {
2323

2424
// Dependencies of the menu lib.
2525
dependency_provider.add_dependencies("menu", (1, 0, 0), [
26-
("dropdown", Range::strictly_lower_than((2, 0, 0))),
26+
("dropdown", Range::from_range_bounds(..(2, 0, 0))),
2727
]);
2828
dependency_provider.add_dependencies("menu", (1, 1, 0), [
29-
("dropdown", Range::higher_than((2, 0, 0))),
29+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3030
]);
3131
dependency_provider.add_dependencies("menu", (1, 2, 0), [
32-
("dropdown", Range::higher_than((2, 0, 0))),
32+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3333
]);
3434
dependency_provider.add_dependencies("menu", (1, 3, 0), [
35-
("dropdown", Range::higher_than((2, 0, 0))),
35+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3636
]);
3737
dependency_provider.add_dependencies("menu", (1, 4, 0), [
38-
("dropdown", Range::higher_than((2, 0, 0))),
38+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
3939
]);
4040
dependency_provider.add_dependencies("menu", (1, 5, 0), [
41-
("dropdown", Range::higher_than((2, 0, 0))),
41+
("dropdown", Range::from_range_bounds((2, 0, 0)..)),
4242
]);
4343

4444
// Dependencies of the dropdown lib.

examples/linear_error_reporting.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ fn main() {
1414
dependency_provider.add_dependencies(
1515
"root", (1, 0, 0),
1616
[
17-
("foo", Range::between((1, 0, 0), (2, 0, 0))),
18-
("baz", Range::between((1, 0, 0), (2, 0, 0))),
17+
("foo", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
18+
("baz", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
1919
],
2020
);
2121
#[rustfmt::skip]
2222
// foo 1.0.0 depends on bar ^2.0.0
2323
dependency_provider.add_dependencies(
2424
"foo", (1, 0, 0),
25-
[("bar", Range::between((2, 0, 0), (3, 0, 0)))],
25+
[("bar", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))],
2626
);
2727
#[rustfmt::skip]
2828
// bar 2.0.0 depends on baz ^3.0.0
2929
dependency_provider.add_dependencies(
3030
"bar", (2, 0, 0),
31-
[("baz", Range::between((3, 0, 0), (4, 0, 0)))],
31+
[("baz", Range::from_range_bounds((3, 0, 0)..(4, 0, 0)))],
3232
);
3333
// baz 1.0.0 and 3.0.0 have no dependencies
3434
dependency_provider.add_dependencies("baz", (1, 0, 0), []);

src/range.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
use std::cmp::Ordering;
1818
use std::fmt;
19+
use std::ops::{Bound, RangeBounds};
1920

2021
use crate::internal::small_vec::SmallVec;
2122
use crate::version::Version;
@@ -85,6 +86,31 @@ impl<V: Version> Range<V> {
8586
Self::none()
8687
}
8788
}
89+
90+
/// Construct a simple range from anything that impls [RangeBounds] like `v1..v2`.
91+
pub fn from_range_bounds<R, IV>(bounds: R) -> Self
92+
where
93+
R: RangeBounds<IV>,
94+
for<'a> &'a IV: Into<V>,
95+
{
96+
let start = match bounds.start_bound() {
97+
Bound::Included(s) => s.into(),
98+
Bound::Excluded(s) => s.into().bump(),
99+
Bound::Unbounded => V::lowest(),
100+
};
101+
let end = match bounds.end_bound() {
102+
Bound::Included(e) => Some(e.into().bump()),
103+
Bound::Excluded(e) => Some(e.into()),
104+
Bound::Unbounded => None,
105+
};
106+
if end.is_some() && end.as_ref() <= Some(&start) {
107+
Self::none()
108+
} else {
109+
Self {
110+
segments: SmallVec::one((start, end)),
111+
}
112+
}
113+
}
88114
}
89115

90116
// Set operations.
@@ -260,6 +286,24 @@ impl<V: Version> Range<V> {
260286
pub fn lowest_version(&self) -> Option<V> {
261287
self.segments.first().map(|(start, _)| start).cloned()
262288
}
289+
290+
/// Convert to something that can be used with
291+
/// [BTreeMap::range](std::collections::BTreeMap::range).
292+
/// All versions contained in self, will be in the output,
293+
/// but there may be versions in the output that are not contained in self.
294+
/// Returns None if the range is empty.
295+
pub fn bounding_range(&self) -> Option<(Bound<&V>, Bound<&V>)> {
296+
self.segments.first().map(|(start, _)| {
297+
let end = {
298+
self.segments
299+
.last()
300+
.and_then(|(_, l)| l.as_ref())
301+
.map(Bound::Excluded)
302+
.unwrap_or(Bound::Unbounded)
303+
};
304+
(Bound::Included(start), end)
305+
})
306+
}
263307
}
264308

265309
// REPORT ######################################################################
@@ -405,5 +449,25 @@ pub mod tests {
405449
fn contains_intersection(range in strategy(), version in version_strat()) {
406450
assert_eq!(range.contains(&version), range.intersection(&Range::exact(version)) != Range::none());
407451
}
452+
453+
#[test]
454+
fn contains_bounding_range(range in strategy(), version in version_strat()) {
455+
if range.contains(&version) {
456+
assert!(range.bounding_range().map(|b| b.contains(&version)).unwrap_or(false));
457+
}
458+
}
459+
460+
#[test]
461+
fn from_range_bounds(range in any::<(Bound<u32>, Bound<u32>)>(), version in version_strat()) {
462+
let rv: Range<NumberVersion> = Range::from_range_bounds(range);
463+
assert_eq!(range.contains(&version.0), rv.contains(&version));
464+
}
465+
466+
#[test]
467+
fn from_range_bounds_round_trip(range in any::<(Bound<u32>, Bound<u32>)>()) {
468+
let rv: Range<NumberVersion> = Range::from_range_bounds(range);
469+
let rv2: Range<NumberVersion> = rv.bounding_range().map(Range::from_range_bounds::<_, NumberVersion>).unwrap_or_else(Range::none);
470+
assert_eq!(rv, rv2);
471+
}
408472
}
409473
}

src/version.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ impl From<(u32, u32, u32)> for SemanticVersion {
8080
}
8181
}
8282

83+
// Convert a &(major, minor, patch) into a version.
84+
impl From<&(u32, u32, u32)> for SemanticVersion {
85+
fn from(tuple: &(u32, u32, u32)) -> Self {
86+
let (major, minor, patch) = *tuple;
87+
Self::new(major, minor, patch)
88+
}
89+
}
90+
91+
// Convert an &version into a version.
92+
impl From<&SemanticVersion> for SemanticVersion {
93+
fn from(v: &SemanticVersion) -> Self {
94+
*v
95+
}
96+
}
97+
8398
// Convert a version into a tuple (major, minor, patch).
8499
impl From<SemanticVersion> for (u32, u32, u32) {
85100
fn from(v: SemanticVersion) -> Self {
@@ -237,6 +252,20 @@ impl From<u32> for NumberVersion {
237252
}
238253
}
239254

255+
// Convert an &usize into a version.
256+
impl From<&u32> for NumberVersion {
257+
fn from(v: &u32) -> Self {
258+
Self(*v)
259+
}
260+
}
261+
262+
// Convert an &version into a version.
263+
impl From<&NumberVersion> for NumberVersion {
264+
fn from(v: &NumberVersion) -> Self {
265+
*v
266+
}
267+
}
268+
240269
// Convert a version into an usize.
241270
impl From<NumberVersion> for u32 {
242271
fn from(version: NumberVersion) -> Self {

0 commit comments

Comments
 (0)