lune/crates/lune-std-ffi/src/ffi/ffi_ref/bounds.rs
2024-10-13 05:09:31 +00:00

100 lines
2.4 KiB
Rust

use std::clone;
// Memory range for ref or box data. For boundary checking
pub struct FfiRefBounds {
// Indicates how much data is above the pointer
pub(crate) above: usize,
// Indicates how much data is below the pointer
pub(crate) below: usize,
}
pub const UNSIZED_BOUNDS: FfiRefBounds = FfiRefBounds {
above: usize::MAX,
below: usize::MAX,
};
impl FfiRefBounds {
pub fn new(above: usize, below: usize) -> Self {
Self { above, below }
}
pub fn is_unsized(&self) -> bool {
self.above == usize::MAX && self.below == usize::MAX
}
// Check boundary
pub fn check_boundary(&self, offset: isize) -> bool {
if self.is_unsized() {
return true;
}
let sign = offset.signum();
let offset_abs = offset.unsigned_abs();
if sign == -1 {
self.above >= offset_abs
} else if sign == 1 {
self.below >= offset_abs
} else {
// sign == 0
true
}
}
// Check boundary
// Check required here
pub fn check_sized(&self, offset: isize, size: usize) -> bool {
if self.is_unsized() {
return true;
}
if offset < 0 && self.above < offset.unsigned_abs() {
return true;
}
let end = offset + (size as isize) - 1;
let end_sign = end.signum();
let end_abs = end.unsigned_abs();
if end_sign == -1 {
self.above >= end_abs
} else if end_sign == 1 {
self.below >= end_abs
} else {
// sign == 0
true
}
}
// Calculate new bounds from bounds and offset
// No boundary checking in here
pub fn offset(&self, offset: isize) -> Self {
let sign = offset.signum();
let offset_abs = offset.unsigned_abs();
let high: usize = if sign == -1 {
self.above - offset_abs
} else if sign == 1 {
self.above + offset_abs
} else {
self.above
};
let low: usize = if sign == -1 {
self.below + offset_abs
} else if sign == 1 {
self.below - offset_abs
} else {
self.below
};
Self {
above: high,
below: low,
}
}
}
impl Clone for FfiRefBounds {
fn clone(&self) -> Self {
Self {
above: self.above,
below: self.below,
}
}
}