use std::ops::{Deref, DerefMut};
use std::io;
use memmap2::{Mmap, MmapMut};
use crate::AssemblyOffset;
#[derive(Debug, Default)]
pub struct ExecutableBuffer {
length: usize,
buffer: Option<Mmap>
}
#[derive(Debug, Default)]
pub struct MutableBuffer {
length: usize,
buffer: Option<MmapMut>
}
impl ExecutableBuffer {
pub fn ptr(&self, offset: AssemblyOffset) -> *const u8 {
&self[offset.0] as *const u8
}
pub fn new(size: usize) -> io::Result<ExecutableBuffer> {
let buffer = if size == 0 {
None
} else {
Some(MmapMut::map_anon(size)?.make_exec()?)
};
Ok(ExecutableBuffer {
length: 0,
buffer
})
}
pub fn size(&self) -> usize {
self.buffer.as_ref().map(|b| b.len()).unwrap_or(0)
}
pub fn make_mut(self) -> io::Result<MutableBuffer> {
let buffer = if let Some(map) = self.buffer {
Some(map.make_mut()?)
} else {
None
};
Ok(MutableBuffer {
length: self.length,
buffer
})
}
}
impl MutableBuffer {
pub fn new(size: usize) -> io::Result<MutableBuffer> {
let buffer = if size == 0 {
None
} else {
Some(MmapMut::map_anon(size)?)
};
Ok(MutableBuffer {
length: 0,
buffer
})
}
pub fn size(&self) -> usize {
self.buffer.as_ref().map(|b| b.len()).unwrap_or(0)
}
pub fn set_len(&mut self, length: usize) {
self.length = length
}
pub fn make_exec(self) -> io::Result<ExecutableBuffer> {
let buffer = if let Some(map) = self.buffer {
Some(map.make_exec()?)
} else {
None
};
Ok(ExecutableBuffer {
length: self.length,
buffer
})
}
}
impl Deref for ExecutableBuffer {
type Target = [u8];
fn deref(&self) -> &[u8] {
if let Some(map) = &self.buffer {
&map[..self.length]
} else {
&[]
}
}
}
impl Deref for MutableBuffer {
type Target = [u8];
fn deref(&self) -> &[u8] {
if let Some(map) = &self.buffer {
&map[..self.length]
} else {
&[]
}
}
}
impl DerefMut for MutableBuffer {
fn deref_mut(&mut self) -> &mut [u8] {
if let Some(map) = &mut self.buffer {
&mut map[..self.length]
} else {
&mut []
}
}
}