memflow 0.2.0-beta9

core components of the memflow physical memory introspection framework
Documentation
use crate::mem::mem_data::{MemoryRange, MemoryRangeCallback};
use crate::types::{imem, umem, Address, PageType};
use cglue::prelude::v1::*;
use std::prelude::v1::*;

pub struct GapRemover<'a> {
    map: rangemap::RangeMap<Address, PageType>,
    out: Option<MemoryRangeCallback<'a>>,
    gap_size: imem,
    start: Address,
    end: Address,
}

impl<'a> GapRemover<'a> {
    pub fn new(out: MemoryRangeCallback<'a>, gap_size: imem, start: Address, end: Address) -> Self {
        Self {
            map: Default::default(),
            out: Some(out),
            gap_size,
            start,
            end,
        }
    }

    pub fn push_range(&mut self, CTup3(in_virtual, size, page_type): MemoryRange) {
        self.map.insert(in_virtual..(in_virtual + size), page_type);
    }
}

impl<'a> Drop for GapRemover<'a> {
    fn drop(&mut self) {
        self.map
            .gaps(&(self.start..self.end))
            .filter_map(|r| {
                assert!(r.end >= r.start);
                if self.gap_size >= 0 && (r.end - r.start) as umem <= self.gap_size as umem {
                    if r.start.to_umem() > 0 {
                        let next = r.end;
                        let prev = r.start - 1 as umem;
                        match (self.map.get(&prev), self.map.get(&next)) {
                            (Some(p1), Some(p2)) if p1 == p2 => Some((r, *p2)),
                            _ => None,
                        }
                    } else {
                        None
                    }
                } else {
                    None
                }
            })
            .collect::<Vec<_>>()
            .into_iter()
            .for_each(|(r, p)| self.map.insert(r, p));

        self.map
            .iter()
            .map(|(r, p)| {
                let address = r.start;
                assert!(r.end >= address);
                let size = r.end - address;
                CTup3(address, size as umem, *p)
            })
            .feed_into(self.out.take().unwrap());
    }
}

impl<'a> Extend<MemoryRange> for GapRemover<'a> {
    fn extend<T>(&mut self, iter: T)
    where
        T: IntoIterator<Item = MemoryRange>,
    {
        iter.into_iter().for_each(|r| self.push_range(r));
    }
}