#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
fmt::Display,
hash::Hash,
ops::{Deref, DerefMut, Index, IndexMut, Range, RangeBounds},
slice::SliceIndex,
};
use crate::Error;
const DEFAULT_CHUNCK_SIZE: usize = 32;
#[derive(Clone, Eq, Ord, PartialOrd, Debug, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Segment {
minimum_address: usize,
data: Vec<u8>,
}
impl Segment {
pub fn new<T>(minimum_address: usize, data: T) -> Self
where
T: AsRef<[u8]>,
{
Self {
minimum_address,
data: Vec::from(data.as_ref()),
}
}
pub fn minimum_address(&self) -> usize {
self.minimum_address
}
pub fn chunks(
&self,
size: Option<usize>,
alignment: Option<usize>,
) -> Result<BTreeMap<usize, Vec<u8>>, Error> {
let size = size.unwrap_or(DEFAULT_CHUNCK_SIZE);
let alignment = alignment.unwrap_or(1);
if size % alignment != 0 {
Err(Error::AlignmentToSizeError { size, alignment })
} else {
let mut address = self.minimum_address;
let mut data = self.data.to_vec();
let mut chunks: BTreeMap<usize, Vec<u8>> = BTreeMap::new();
let chunk_offset = address % alignment;
if chunk_offset != 0 {
let first_chunk_size = alignment - chunk_offset;
if first_chunk_size > data.len() {
chunks.insert(address, data.clone());
data.clear();
} else {
chunks.insert(address, data[..first_chunk_size].to_vec());
address += first_chunk_size;
data = data[first_chunk_size..].to_vec();
}
}
for (index, chunk) in data.chunks(size).enumerate() {
chunks.insert(address + (index * size), chunk.to_vec());
}
Ok(chunks)
}
}
fn maximum_address(&self) -> usize {
self.minimum_address + self.data.len()
}
pub fn get_tuple(&self) -> (usize, &Vec<u8>) {
(self.minimum_address(), &self.data)
}
pub fn add_data(
&mut self,
minimum_address: usize,
data: Vec<u8>,
overwrite: bool,
) -> Result<(), Error> {
let maximum_address = minimum_address + data.len();
if minimum_address == self.maximum_address() {
let mut new_data = data;
self.data.append(&mut new_data);
Ok(())
} else if maximum_address == self.minimum_address {
self.minimum_address = minimum_address;
let mut new_data = data;
new_data.append(&mut self.data);
self.data = new_data;
Ok(())
} else if overwrite
&& minimum_address < self.maximum_address()
&& maximum_address > self.minimum_address
{
let mut self_data_offset = minimum_address as i64 - self.minimum_address as i64;
let mut data = data;
if self_data_offset < 0 {
self_data_offset *= -1;
let mut new_data = data[..self_data_offset as usize].to_vec();
new_data.append(&mut self.data);
self.data = new_data;
data = data[self_data_offset as usize..].to_vec();
self.minimum_address = minimum_address;
}
let self_data_left = self.data.len() - self_data_offset as usize;
if data.len() <= self_data_left {
for (pos, value) in data.iter().enumerate() {
self.data[pos + self_data_offset as usize] = *value;
}
data = Vec::new()
} else {
for (pos, value) in data[..self_data_left].iter().enumerate() {
self.data[pos + self_data_offset as usize] = *value;
}
data = data[self_data_left..].to_vec();
}
if !data.is_empty() {
self.data.append(&mut data);
}
Ok(())
} else {
Err(Error::AddDataError)
}
}
fn remove_data(&mut self, range: &Range<usize>) -> Option<Self> {
let mut minimum_address = range.start;
let mut maximum_address = range.end;
if minimum_address >= self.maximum_address() || maximum_address <= self.minimum_address {
return None;
}
if minimum_address < self.minimum_address {
minimum_address = self.minimum_address;
}
if maximum_address > self.maximum_address() {
maximum_address = self.maximum_address()
}
let remove_size = maximum_address - minimum_address;
let part1_size = minimum_address - self.minimum_address;
let (part1_data, part_data) = self.data.split_at(part1_size);
let (_, part2_data) = part_data.split_at(remove_size);
if !part1_data.is_empty() && !part2_data.is_empty() {
let data2 = part2_data.to_vec();
self.data = part1_data.to_vec();
Some(Self::new(maximum_address, data2))
} else {
if !part1_data.is_empty() {
self.data = part1_data.to_vec();
} else if !part2_data.is_empty() {
self.minimum_address = maximum_address;
self.data = part2_data.to_vec();
} else {
self.data = Vec::new();
}
None
}
}
pub fn get_value_by_address(&self, address: usize) -> Option<u8> {
if address >= self.minimum_address && address < self.maximum_address() {
let pos = address - self.minimum_address;
return Some(self.data[pos]);
}
None
}
pub fn get_values_by_address_range<R: RangeBounds<usize>>(
&self,
address_range: &R,
) -> Option<Vec<u8>> {
let start = match address_range.start_bound() {
std::ops::Bound::Included(val) => *val,
std::ops::Bound::Excluded(val) => *val + 1,
std::ops::Bound::Unbounded => self.minimum_address,
};
let end = match address_range.end_bound() {
std::ops::Bound::Included(val) => *val + 1,
std::ops::Bound::Excluded(val) => *val,
std::ops::Bound::Unbounded => self.maximum_address(),
};
if start >= self.minimum_address
&& start <= self.maximum_address()
&& end <= self.maximum_address()
{
let start = start - self.minimum_address;
let end = end - self.minimum_address;
return Some(self.data[start..end].to_vec());
}
None
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn data(&self) -> &[u8] {
self.data.as_ref()
}
}
impl Display for Segment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Segment(address={}, data={:?})",
self.minimum_address(),
self.data
)
}
}
impl<I> Index<I> for Segment
where
I: SliceIndex<[u8]>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
self.data.index(index)
}
}
impl<I> IndexMut<I> for Segment
where
I: SliceIndex<[u8]>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.data.index_mut(index)
}
}
impl Deref for Segment {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.data.deref()
}
}
impl DerefMut for Segment {
fn deref_mut(&mut self) -> &mut Self::Target {
self.data.deref_mut()
}
}
impl IntoIterator for Segment {
type Item = u8;
type IntoIter = std::vec::IntoIter<u8>;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
}
}
impl<'a> IntoIterator for &'a Segment {
type Item = &'a u8;
type IntoIter = core::slice::Iter<'a, u8>;
fn into_iter(self) -> Self::IntoIter {
self.data.iter()
}
}
impl<'a> IntoIterator for &'a mut Segment {
type Item = &'a mut u8;
type IntoIter = core::slice::IterMut<'a, u8>;
fn into_iter(self) -> Self::IntoIter {
self.data.iter_mut()
}
}
impl AsRef<Segment> for Segment {
fn as_ref(&self) -> &Segment {
self
}
}
impl AsMut<Segment> for Segment {
fn as_mut(&mut self) -> &mut Segment {
self
}
}
impl AsRef<[u8]> for Segment {
fn as_ref(&self) -> &[u8] {
self
}
}
impl AsMut<[u8]> for Segment {
fn as_mut(&mut self) -> &mut [u8] {
self
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Segments {
list: Vec<Segment>,
current_segment_index: Option<usize>,
}
impl Segments {
pub fn new() -> Self {
Self {
list: Vec::new(),
current_segment_index: None,
}
}
pub fn len(&self) -> usize {
self.list.len()
}
pub fn is_empty(&self) -> bool {
self.list.is_empty()
}
pub fn get_minimum_address(&self) -> Option<usize> {
self.list.first().map(|first| first.minimum_address)
}
pub fn get_maximum_address(&self) -> Option<usize> {
self.list.last().map(|last| last.maximum_address())
}
pub fn add_segment(&mut self, segment: Segment, overwrite: bool) -> Result<(), Error> {
if !self.list.is_empty() {
if let Some(current_segment_index) = self.current_segment_index {
let current_segment = self.list.get_mut(current_segment_index).unwrap();
if segment.minimum_address == current_segment.maximum_address() {
current_segment.add_data(segment.minimum_address, segment.data, overwrite)?;
} else {
let mut index = 0;
for (i, s) in self.list.iter().enumerate() {
index = i;
if segment.minimum_address <= s.maximum_address() {
break;
}
}
let seg = self.index_mut(index);
if segment.minimum_address > seg.maximum_address() {
self.list.push(segment);
} else if segment.maximum_address() < seg.minimum_address {
self.list.insert(index, segment);
} else {
seg.add_data(segment.minimum_address, segment.data, overwrite)?;
}
self.current_segment_index = Some(index);
}
}
while self.current_segment_index.unwrap() != self.list.len() - 1 {
let list2 = self.list.clone();
let current_segment = self
.list
.get_mut(self.current_segment_index.unwrap())
.unwrap();
let s = list2.get(self.current_segment_index.unwrap() + 1).unwrap();
if current_segment.maximum_address() >= s.maximum_address() {
self.list.remove(self.current_segment_index.unwrap() + 1);
} else if current_segment.maximum_address() >= s.minimum_address {
current_segment.add_data(
current_segment.maximum_address(),
s.data[(current_segment.maximum_address() - s.minimum_address)..].to_vec(),
false,
)?;
self.list.remove(self.current_segment_index.unwrap() + 1);
break;
} else {
break;
}
}
} else {
self.list.push(segment);
self.current_segment_index = Some(0);
}
Ok(())
}
pub fn remove(&mut self, range: Range<usize>) {
let mut new_list: Vec<Segment> = Vec::new();
for segment in self.list.iter_mut() {
let split = segment.remove_data(&range);
if segment.minimum_address < segment.maximum_address() {
new_list.push(segment.clone());
}
if let Some(split) = split {
new_list.push(split);
}
}
self.list = new_list;
}
pub fn chunks(
&self,
size: Option<usize>,
alignment: Option<usize>,
) -> Result<BTreeMap<usize, Vec<u8>>, Error> {
let size = size.unwrap_or(DEFAULT_CHUNCK_SIZE);
let alignment = alignment.unwrap_or(1);
if (size % alignment) != 0 {
Err(Error::AlignmentToSizeError { size, alignment })
} else {
let mut chunks = BTreeMap::new();
for segment in self.list.clone() {
if let Ok(mut segment_chunks) = segment.chunks(Some(size), Some(alignment)) {
chunks.append(&mut segment_chunks);
}
}
Ok(chunks)
}
}
pub fn get_value_by_address(&self, address: usize) -> Option<u8> {
if let (Some(minimum_address), Some(maximum_address)) =
(self.get_minimum_address(), self.get_maximum_address())
{
if address >= minimum_address && address < maximum_address {
for segment in self.list.clone() {
if let Some(value) = segment.get_value_by_address(address) {
return Some(value);
}
}
}
}
None
}
pub fn get_values_by_address_range<R: RangeBounds<usize>>(
&self,
address_range: &R,
) -> Option<Vec<u8>> {
if let (Some(minimum_address), Some(maximum_address)) =
(self.get_minimum_address(), self.get_maximum_address())
{
let start = match address_range.start_bound() {
std::ops::Bound::Included(val) => *val,
std::ops::Bound::Excluded(val) => *val + 1,
std::ops::Bound::Unbounded => minimum_address,
};
let end = match address_range.end_bound() {
std::ops::Bound::Included(val) => *val + 1,
std::ops::Bound::Excluded(val) => *val,
std::ops::Bound::Unbounded => maximum_address,
};
if start >= minimum_address && end <= maximum_address {
for segment in self.list.clone() {
if let Some(value) = segment.get_values_by_address_range(address_range) {
return Some(value);
}
}
}
}
None
}
pub fn segments(&self) -> &[Segment] {
self.list.as_slice()
}
}
impl Default for Segments {
fn default() -> Self {
Self::new()
}
}
impl<I> Index<I> for Segments
where
I: SliceIndex<[Segment]>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
self.list.index(index)
}
}
impl<I> IndexMut<I> for Segments
where
I: SliceIndex<[Segment]>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.list.index_mut(index)
}
}
impl Deref for Segments {
type Target = [Segment];
fn deref(&self) -> &Self::Target {
self.list.deref()
}
}
impl DerefMut for Segments {
fn deref_mut(&mut self) -> &mut Self::Target {
self.list.deref_mut()
}
}
impl IntoIterator for Segments {
type Item = Segment;
type IntoIter = std::vec::IntoIter<Segment>;
fn into_iter(self) -> Self::IntoIter {
self.list.into_iter()
}
}
impl<'a> IntoIterator for &'a Segments {
type Item = &'a Segment;
type IntoIter = core::slice::Iter<'a, Segment>;
fn into_iter(self) -> Self::IntoIter {
self.list.iter()
}
}
impl<'a> IntoIterator for &'a mut Segments {
type Item = &'a mut Segment;
type IntoIter = core::slice::IterMut<'a, Segment>;
fn into_iter(self) -> Self::IntoIter {
self.list.iter_mut()
}
}
impl AsRef<Segments> for Segments {
fn as_ref(&self) -> &Segments {
self
}
}
impl AsMut<Segments> for Segments {
fn as_mut(&mut self) -> &mut Segments {
self
}
}
impl AsRef<[Segment]> for Segments {
fn as_ref(&self) -> &[Segment] {
self
}
}
impl AsMut<[Segment]> for Segments {
fn as_mut(&mut self) -> &mut [Segment] {
self
}
}
impl Display for Segments {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for segment in self.list.clone() {
writeln!(f, "{}", segment)?
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_iterate_segments() {
let mut segments = Segments::default();
let segment_1 = Segment::new(0, [1, 2]);
assert!(segments.add_segment(segment_1.clone(), false).is_ok());
let segment_2 = Segment::new(10, [3, 4]);
assert!(segments.add_segment(segment_2.clone(), false).is_ok());
let mut iter = segments.into_iter();
assert_eq!(iter.next(), Some(segment_1));
assert_eq!(iter.next(), Some(segment_2));
assert_eq!(iter.next(), None);
}
#[test]
fn test_get_tuple() {
let segment_1 = Segment::new(0, [1, 2]);
assert_eq!(segment_1.get_tuple(), (0, &vec![1, 2]));
}
#[test]
fn test_segments_list() {
let mut segments = Segments::default();
let segment_1 = Segment::new(0, [1, 2]);
assert!(segments.add_segment(segment_1.clone(), false).is_ok());
let segment_2 = Segment::new(10, [3, 4]);
assert!(segments.add_segment(segment_2.clone(), false).is_ok());
assert_eq!(segments.segments(), &[segment_1, segment_2]);
}
#[test]
fn test_chunks_list() {
let mut segments = Segments::default();
assert!(segments
.add_segment(Segment::new(0, [0x00, 0x00, 0x01, 0x01, 0x02]), false)
.is_ok());
assert!(segments
.add_segment(Segment::new(9, [0x04, 0x05, 0x05, 0x06, 0x06, 0x07]), false)
.is_ok());
assert!(segments
.add_segment(Segment::new(19, [0x09]), false)
.is_ok());
assert!(segments
.add_segment(Segment::new(21, [0x0a]), false)
.is_ok());
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01, 0x02]);
data.insert(9, vec![0x04, 0x05, 0x05, 0x06, 0x06, 0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(8), None), Ok(data));
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01, 0x02]);
data.insert(9, vec![0x04]);
data.insert(10, vec![0x05, 0x05, 0x06, 0x06, 0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(8), Some(2)), Ok(data));
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01, 0x02]);
data.insert(9, vec![0x04, 0x05, 0x05]);
data.insert(12, vec![0x06, 0x06, 0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(8), Some(4)), Ok(data));
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01, 0x02]);
data.insert(9, vec![0x04, 0x05, 0x05, 0x06, 0x06, 0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(8), Some(8)), Ok(data));
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01]);
data.insert(4, vec![0x02]);
data.insert(9, vec![0x04, 0x05, 0x05, 0x06]);
data.insert(13, vec![0x06, 0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(4), None), Ok(data));
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01]);
data.insert(4, vec![0x02]);
data.insert(9, vec![0x04]);
data.insert(10, vec![0x05, 0x05, 0x06, 0x06]);
data.insert(14, vec![0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(4), Some(2)), Ok(data));
let mut data = BTreeMap::new();
data.insert(0, vec![0x00, 0x00, 0x01, 0x01]);
data.insert(4, vec![0x02]);
data.insert(9, vec![0x04, 0x05, 0x05]);
data.insert(12, vec![0x06, 0x06, 0x07]);
data.insert(19, vec![0x09]);
data.insert(21, vec![0x0a]);
assert_eq!(segments.chunks(Some(4), Some(4)), Ok(data));
}
#[test]
fn test_segment() {
let segment = Segment::new(2, [0x00, 0x01, 0x02, 0x03, 0x04]);
let mut data = BTreeMap::new();
data.insert(2, vec![0x00, 0x01]);
data.insert(4, vec![0x02, 0x03, 0x04]);
assert_eq!(segment.chunks(Some(4), Some(4)), Ok(data));
assert_eq!(
segment.chunks(Some(4), Some(8)),
Err(Error::AlignmentToSizeError {
size: 4,
alignment: 8
})
)
}
}