#![cfg_attr(not(feature = "std"), no_std)]
#![feature(btree_drain_filter)]
#[cfg(feature = "std")]
mod external {
pub use std::collections::btree_map::{Iter, IterMut};
pub use std::{collections::BTreeMap, fmt::Debug, iter::Iterator, vec::Vec};
}
#[cfg(not(feature = "std"))]
mod external {
extern crate alloc;
pub use alloc::collections::btree_map::{Iter, IterMut};
pub use alloc::collections::BTreeMap;
pub use alloc::vec::Vec;
pub use core::fmt::Debug;
pub use core::iter::Iterator;
}
use external::*;
mod segment;
pub use segment::Segment;
mod set;
pub use set::{CutSet, DiffSet};
mod range_area;
pub use range_area::RangeArea;
mod defs;
pub use defs::{ArgsType, IdentType, LOWER_LIMIT, UPPER_LIMIT};
pub struct RangeActionMap<SegmentType: Segment> {
pub segments: BTreeMap<usize, RangeArea<SegmentType>>,
args: ArgsType,
}
impl<SegmentType: Segment> RangeActionMap<SegmentType> {
pub fn new(args: ArgsType) -> Self {
Self {
segments: BTreeMap::new(),
args,
}
}
fn insert_raw(&mut self, start: usize, end: usize, segment: SegmentType) {
self.segments.insert(
start,
RangeArea {
start,
end,
segment,
},
);
}
pub fn find<'a>(&'a self, pos: usize) -> Option<&'a SegmentType> {
if let Some((_, area)) = self.segments.range(..=pos).last() {
if area.contains(pos) {
return Some(&area.segment);
}
}
None
}
pub fn iter<'a>(&'a self) -> RangeActionMapIter<'a, SegmentType> {
RangeActionMapIter {
map_iter: self.segments.iter(),
}
}
pub fn iter_mut<'a>(&'a mut self) -> RangeActionMapIterMut<'a, SegmentType> {
RangeActionMapIterMut {
map_iter: self.segments.iter_mut(),
}
}
pub fn mmap_anywhere(
&mut self,
hint: usize,
len: usize,
f: impl FnOnce(usize) -> SegmentType,
) -> Option<usize> {
self.find_free_area(hint, len).map(|start| {
self.insert_raw(start, start + len, f(start));
start
})
}
pub fn mmap_fixed(
&mut self,
start: usize,
end: usize,
f: impl FnOnce() -> SegmentType,
) -> Option<usize> {
if start < LOWER_LIMIT || end > UPPER_LIMIT {
return None;
}
self.unmap(start, end);
self.insert_raw(start, end, f());
Some(start)
}
pub fn unmap(&mut self, start: usize, end: usize) {
let areas_to_be_modified: Vec<RangeArea<SegmentType>> = self
.segments
.drain_filter(|_, area| area.is_overlap_with(start, end))
.map(|(_, v)| v)
.collect();
for mut area in areas_to_be_modified {
match area.shrink_or_split_if_overlap(start, end, self.args) {
DiffSet::Shrinked => {
self.segments.insert(area.start, area);
}
DiffSet::Splitted(right) => {
self.segments.insert(area.start, area);
self.segments.insert(right.start, right);
}
_ => {} }
}
}
pub fn mprotect(&mut self, start: usize, end: usize, new_flags: IdentType) {
let areas_to_be_modified: Vec<RangeArea<SegmentType>> = self
.segments
.drain_filter(|_, area| area.is_overlap_with(start, end))
.map(|(_, v)| v)
.collect();
for mut area in areas_to_be_modified {
match area.split_and_modify_if_overlap(start, end, new_flags, self.args) {
CutSet::WholeModified => {
self.segments.insert(area.start, area);
}
CutSet::ModifiedLeft(right) | CutSet::ModifiedRight(right) => {
self.segments.insert(area.start, area);
self.segments.insert(right.start, right);
}
CutSet::ModifiedMiddle(mid, right) => {
self.segments.insert(area.start, area);
self.segments.insert(mid.start, mid);
self.segments.insert(right.start, right);
}
_ => {} }
}
}
pub fn find_free_area(&self, hint: usize, len: usize) -> Option<usize> {
let mut last_seg_end = hint.max(LOWER_LIMIT);
for (start, seg) in self.segments.iter() {
if last_seg_end + len <= *start {
return Some(last_seg_end);
}
last_seg_end = last_seg_end.max(seg.end);
}
if last_seg_end + len <= UPPER_LIMIT {
Some(last_seg_end)
} else {
None
}
}
}
impl<SegmentType: Segment + Debug> Debug for RangeActionMap<SegmentType> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("RangeActionMap")
.field("segments", &self.segments.values())
.finish()
}
}
pub struct RangeActionMapIter<'a, SegmentType: Segment> {
map_iter: Iter<'a, usize, RangeArea<SegmentType>>,
}
impl<'a, SegmentType: Segment> Iterator for RangeActionMapIter<'a, SegmentType> {
type Item = &'a SegmentType;
fn next(&mut self) -> Option<Self::Item> {
self.map_iter.next().map(|(_, area)| &area.segment)
}
}
pub struct RangeActionMapIterMut<'a, SegmentType: Segment> {
map_iter: IterMut<'a, usize, RangeArea<SegmentType>>,
}
impl<'a, SegmentType: Segment> Iterator for RangeActionMapIterMut<'a, SegmentType> {
type Item = &'a mut SegmentType;
fn next(&mut self) -> Option<Self::Item> {
self.map_iter.next().map(|(_, area)| &mut area.segment)
}
}