Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
collective
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Eduardo Trujillo
collective
Commits
5fe51129
Commit
5fe51129
authored
3 weeks ago
by
Eduardo Trujillo
Browse files
Options
Downloads
Patches
Plain Diff
feat(rangeset): Introduce a range set data structure
parent
28c45be9
Loading
Loading
No related merge requests found
Checking pipeline status
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/lib.rs
+2
-0
2 additions, 0 deletions
src/lib.rs
src/rangeset.rs
+110
-0
110 additions, 0 deletions
src/rangeset.rs
with
112 additions
and
0 deletions
src/lib.rs
+
2
−
0
View file @
5fe51129
...
...
@@ -8,6 +8,8 @@ pub mod cli;
pub
mod
config
;
/// Range dictionary data structure
pub
mod
rangedict
;
/// Range set data structure
pub
mod
rangeset
;
/// Ephemeral working directories.
pub
mod
rundir
;
/// String utilities.
...
...
This diff is collapsed.
Click to expand it.
src/rangeset.rs
0 → 100644
+
110
−
0
View file @
5fe51129
use
std
::
collections
::
BTreeMap
;
use
thiserror
::
Error
;
/// Error type for [`RangeSet`]
#[derive(Error,
Debug,
PartialEq)]
pub
enum
RangeSetError
{
/// Used when an invalid range is provided (e.g. End is before start).
#[error(
"Invalid range provided"
)]
InvalidRange
,
/// Used when an insertion would result in an overlap.
#[error(
"Overlapping ranges"
)]
RangeOverlap
,
}
/// A set of non-overlapping ranges.
#[derive(Debug)]
pub
struct
RangeSet
<
RK
:
Ord
+
Copy
>
{
ranges
:
BTreeMap
<
RK
,
RK
>
,
// Maps start -> end
}
impl
<
RK
:
Ord
+
Copy
>
RangeSet
<
RK
>
{
/// Creates a new empty `RangeSet`.
pub
fn
new
()
->
Self
{
Self
{
ranges
:
BTreeMap
::
new
(),
}
}
/// Inserts a new range `[start, end)`, ensuring no overlaps.
pub
fn
insert
(
&
mut
self
,
start
:
RK
,
end
:
RK
)
->
Result
<
(),
RangeSetError
>
{
if
start
>=
end
{
return
Err
(
RangeSetError
::
InvalidRange
);
}
// Find adjacent or overlapping ranges
if
let
Some
((
&
_prev_start
,
&
prev_end
))
=
self
.ranges
.range
(
..=
start
)
.next_back
()
{
if
prev_end
>=
start
{
return
Err
(
RangeSetError
::
RangeOverlap
);
}
}
if
let
Some
((
&
next_start
,
_
))
=
self
.ranges
.range
(
start
..
)
.next
()
{
if
next_start
<
end
{
return
Err
(
RangeSetError
::
RangeOverlap
);
}
}
self
.ranges
.insert
(
start
,
end
);
Ok
(())
}
/// Checks if a value exists in any range.
pub
fn
contains
(
&
self
,
value
:
RK
)
->
bool
{
if
let
Some
((
&
_start
,
&
end
))
=
self
.ranges
.range
(
..=
value
)
.next_back
()
{
return
value
<
end
;
}
false
}
/// Removes a range if it exists.
pub
fn
remove
(
&
mut
self
,
start
:
RK
,
end
:
RK
)
->
bool
{
if
let
Some
(
range_end
)
=
self
.ranges
.get
(
&
start
)
{
if
*
range_end
==
end
{
self
.ranges
.remove
(
&
start
);
return
true
;
}
}
false
}
/// Returns all stored ranges.
pub
fn
iter
(
&
self
)
->
impl
Iterator
<
Item
=
(
RK
,
RK
)
>
+
'_
{
self
.ranges
.iter
()
.map
(|(
&
s
,
&
e
)|
(
s
,
e
))
}
}
impl
<
RK
:
Copy
+
Ord
>
Default
for
RangeSet
<
RK
>
{
fn
default
()
->
Self
{
RangeSet
::
new
()
}
}
#[cfg(test)]
mod
tests
{
use
crate
::
rangeset
::{
RangeSet
,
RangeSetError
};
#[test]
fn
test_insertions
()
{
let
mut
rs
=
RangeSet
::
new
();
assert_eq!
(
rs
.insert
(
10
,
20
),
Ok
(()));
assert_eq!
(
rs
.insert
(
30
,
40
),
Ok
(()));
assert_eq!
(
rs
.insert
(
15
,
25
),
Err
(
RangeSetError
::
RangeOverlap
));
assert_eq!
(
rs
.contains
(
15
),
true
);
assert_eq!
(
rs
.contains
(
25
),
false
);
}
#[test]
fn
test_removal
()
{
let
mut
rs
=
RangeSet
::
new
();
assert_eq!
(
rs
.insert
(
10
,
20
),
Ok
(()));
assert_eq!
(
rs
.insert
(
30
,
40
),
Ok
(()));
assert_eq!
(
rs
.remove
(
10
,
11
),
false
);
assert_eq!
(
rs
.remove
(
10
,
20
),
true
);
assert_eq!
(
rs
.remove
(
30
,
40
),
true
);
assert_eq!
(
rs
.remove
(
30
,
40
),
false
);
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment