move more stuff to shared test file

This commit is contained in:
janis 2025-10-29 16:20:42 +01:00
parent 86bbab90c3
commit 62751f30ab
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
3 changed files with 297 additions and 270 deletions

View file

@ -1,3 +1,5 @@
#![allow(dead_code)]
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn panic() -> ! { extern "C" fn panic() -> ! {
panic!("Called panic from external code."); panic!("Called panic from external code.");
@ -31,10 +33,297 @@ impl MaybeFFISlice {
} }
impl FFISlice { impl FFISlice {
pub fn as_slice(&self) -> &[u8] { pub unsafe fn as_slice<T: Sized>(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.ptr.cast(), self.len) }
}
pub unsafe fn as_bytes(&self) -> &[u8] {
unsafe { core::slice::from_raw_parts(self.ptr, self.len) } unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
} }
pub fn as_str(&self) -> &str { pub unsafe fn as_str(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(self.as_slice()) } unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
}
}
#[repr(C)]
pub struct BlobVec {
pub data: *mut u8,
pub len: usize,
pub cap: usize,
pub elem_size: usize,
pub drop: Option<extern "C" fn(*mut u8)>,
}
impl Default for BlobVec {
fn default() -> Self {
Self {
data: core::ptr::null_mut(),
len: 0,
cap: 0,
elem_size: 0,
drop: None,
}
}
}
unsafe impl Send for BlobVec {}
unsafe impl Sync for BlobVec {}
pub mod vec {
#![allow(dead_code)]
use super::ffi::*;
use super::*;
pub struct Vec<T> {
pub vec: BlobVec,
_marker: core::marker::PhantomData<T>,
}
impl<T> Vec<T> {
pub fn new() -> Self {
Self::new_with(32)
}
pub fn new_with(capacity: usize) -> Self {
let mut vec = BlobVec {
data: core::ptr::null_mut(),
len: 0,
cap: 0,
elem_size: 0,
drop: None,
};
extern "C" fn drop_fn<T>(ptr: *mut u8) {
unsafe {
core::ptr::drop_in_place::<T>(ptr as *mut T);
}
}
unsafe {
vec_init_with(
&mut vec,
core::mem::size_of::<T>(),
Some(drop_fn::<T>),
capacity,
);
}
Self {
vec,
_marker: core::marker::PhantomData,
}
}
pub fn as_slice(&self) -> &[T] {
assert_eq!(self.vec.elem_size, core::mem::size_of::<T>());
unsafe { core::slice::from_raw_parts(self.vec.data as *const T, self.vec.len) }
}
pub fn as_slice_mut(&mut self) -> &mut [T] {
assert_eq!(self.vec.elem_size, core::mem::size_of::<T>());
unsafe { core::slice::from_raw_parts_mut(self.vec.data as *mut T, self.vec.len) }
}
pub fn push(&mut self, value: T) {
let value = core::mem::ManuallyDrop::new(value);
unsafe {
vec_push(&mut self.vec, &raw const value as *const T as *const u8);
}
}
pub fn insert(&mut self, value: T, index: usize) {
if index > self.vec.len {
return;
}
let value = core::mem::ManuallyDrop::new(value);
unsafe {
vec_insert(
&mut self.vec,
index,
&raw const value as *const T as *const u8,
);
}
}
pub fn pop(&mut self) -> Option<T> {
if self.vec.len == 0 {
return None;
}
unsafe {
let ptr = vec_get(&mut self.vec, self.vec.len - 1) as *mut T;
let value = ptr.read();
vec_pop(&mut self.vec);
Some(value)
}
}
pub fn get(&self, index: usize) -> Option<&T> {
if index >= self.vec.len {
return None;
}
unsafe {
let ptr = vec_get(&raw const self.vec as *mut _, index) as *mut T;
Some(&*ptr)
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index >= self.vec.len {
return None;
}
unsafe {
let ptr = vec_get(&raw mut self.vec, index) as *mut T;
Some(&mut *ptr)
}
}
pub fn remove(&mut self, index: usize) {
if index >= self.vec.len {
return;
}
unsafe {
vec_remove(&mut self.vec, index);
}
}
pub fn len(&self) -> usize {
self.vec.len
}
pub fn position<F>(&self, elem: &T, mut cmp: F) -> Option<usize>
where
F: FnMut(&T, &T) -> bool,
{
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> bool>(
f: *const (),
a: *const u8,
b: *const u8,
) -> bool {
let f = unsafe { &mut *(f as *mut F) };
let a = unsafe { &*(a as *const T) };
let b = unsafe { &*(b as *const T) };
f(a, b)
}
unsafe {
let index = vec_find(
&raw const self.vec as *mut _,
elem as *const T as *const u8,
cmp_trampoline::<T, F>,
&raw mut cmp as *mut F as *mut (),
);
if index == usize::MAX {
None
} else {
Some(index)
}
}
}
pub fn binary_search_by<F>(&self, elem: &T, mut cmp: F) -> Result<usize, usize>
where
F: FnMut(&T, &T) -> i32,
{
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> i32>(
f: *const (),
a: *const u8,
b: *const u8,
) -> i32 {
let f = unsafe { &mut *(f as *mut F) };
let a = unsafe { &*(a as *const T) };
let b = unsafe { &*(b as *const T) };
f(a, b)
}
unsafe {
let (index, vacant) = vec_binary_search_by(
&raw const self.vec as *mut _,
elem as *const T as *const u8,
cmp_trampoline::<T, F>,
&raw mut cmp as *mut F as *mut (),
);
if vacant {
Err(index)
} else {
Ok(index)
}
}
}
pub fn insert_sorted<F>(&self, elem: T, mut cmp: F) -> Result<usize, usize>
where
F: FnMut(&T, &T) -> i32,
{
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> i32>(
f: *const (),
a: *const u8,
b: *const u8,
) -> i32 {
let f = unsafe { &mut *(f as *mut F) };
let a = unsafe { &*(a as *const T) };
let b = unsafe { &*(b as *const T) };
f(a, b)
}
let mut elem = core::mem::ManuallyDrop::new(elem);
unsafe {
let (index, _inserted) = vec_insert_sorted(
&raw const self.vec as *mut _,
&raw mut elem as *const u8,
cmp_trampoline::<T, F>,
&raw mut cmp as *mut F as *mut (),
);
Ok(index)
}
}
}
}
pub mod ffi {
#![allow(improper_ctypes)]
use super::*;
#[allow(dead_code)]
unsafe extern "C" {
pub unsafe fn vec_init(
vec: *mut BlobVec,
elem_size: usize,
drop: Option<extern "C" fn(*mut u8)>,
);
pub unsafe fn vec_init_with(
vec: *mut BlobVec,
elem_size: usize,
drop: Option<extern "C" fn(*mut u8)>,
cap: usize,
);
pub unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8);
pub unsafe fn vec_insert(vec: *mut BlobVec, index: usize, elem: *const u8);
pub unsafe fn vec_pop(vec: *mut BlobVec);
pub unsafe fn vec_drop_last(vec: *mut BlobVec);
pub unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8;
pub unsafe fn vec_remove(vec: *mut BlobVec, index: usize);
pub unsafe fn vec_drop(vec: *mut BlobVec);
pub unsafe fn vec_find(
vec: *mut BlobVec,
elem: *const u8,
cmp: extern "C" fn(*const (), *const u8, *const u8) -> bool,
cmp_data: *mut (),
) -> usize;
pub unsafe fn vec_binary_search_by(
vec: *mut BlobVec,
elem: *const u8,
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
cmp_data: *mut (),
) -> (usize, bool);
pub unsafe fn vec_insert_sorted(
vec: *mut BlobVec,
elem: *const u8,
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
cmp_data: *mut (),
) -> (usize, bool);
} }
} }

View file

@ -18,12 +18,6 @@ impl PartialEq for Lexeme {
impl Eq for Lexeme {} impl Eq for Lexeme {}
impl Lexeme {
fn lex(&self) -> &'static str {
self.1
}
}
trait AsLexeme { trait AsLexeme {
fn as_lexeme(self) -> Option<Lexeme>; fn as_lexeme(self) -> Option<Lexeme>;
} }

View file

@ -1,263 +1,7 @@
#[repr(C)] #[path = "shared/shared.rs"]
pub struct BlobVec { mod util;
pub data: *mut u8,
pub len: usize,
pub cap: usize,
pub elem_size: usize,
pub drop: Option<extern "C" fn(*mut u8)>,
}
struct VecT<T> { use util::{ffi::*, vec::Vec, BlobVec};
vec: BlobVec,
_marker: core::marker::PhantomData<T>,
}
impl<T> VecT<T> {
fn new() -> Self {
Self::new_with(32)
}
fn new_with(capacity: usize) -> Self {
let mut vec = BlobVec {
data: core::ptr::null_mut(),
len: 0,
cap: 0,
elem_size: 0,
drop: None,
};
extern "C" fn drop_fn<T>(ptr: *mut u8) {
unsafe {
core::ptr::drop_in_place::<T>(ptr as *mut T);
}
}
unsafe {
vec_init_with(
&mut vec,
core::mem::size_of::<T>(),
Some(drop_fn::<T>),
capacity,
);
}
Self {
vec,
_marker: core::marker::PhantomData,
}
}
fn as_slice(&self) -> &[T] {
assert_eq!(self.vec.elem_size, core::mem::size_of::<T>());
unsafe { core::slice::from_raw_parts(self.vec.data as *const T, self.vec.len) }
}
fn as_slice_mut(&mut self) -> &mut [T] {
assert_eq!(self.vec.elem_size, core::mem::size_of::<T>());
unsafe { core::slice::from_raw_parts_mut(self.vec.data as *mut T, self.vec.len) }
}
fn push(&mut self, value: T) {
let value = core::mem::ManuallyDrop::new(value);
unsafe {
vec_push(&mut self.vec, &raw const value as *const T as *const u8);
}
}
fn insert(&mut self, value: T, index: usize) {
if index > self.vec.len {
return;
}
let value = core::mem::ManuallyDrop::new(value);
unsafe {
vec_insert(
&mut self.vec,
index,
&raw const value as *const T as *const u8,
);
}
}
fn pop(&mut self) -> Option<T> {
if self.vec.len == 0 {
return None;
}
unsafe {
let ptr = vec_get(&mut self.vec, self.vec.len - 1) as *mut T;
let value = ptr.read();
vec_pop(&mut self.vec);
Some(value)
}
}
fn get(&self, index: usize) -> Option<&T> {
if index >= self.vec.len {
return None;
}
unsafe {
let ptr = vec_get(&raw const self.vec as *mut _, index) as *mut T;
Some(&*ptr)
}
}
fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index >= self.vec.len {
return None;
}
unsafe {
let ptr = vec_get(&raw mut self.vec, index) as *mut T;
Some(&mut *ptr)
}
}
fn remove(&mut self, index: usize) {
if index >= self.vec.len {
return;
}
unsafe {
vec_remove(&mut self.vec, index);
}
}
fn len(&self) -> usize {
self.vec.len
}
fn position<F>(&self, elem: &T, mut cmp: F) -> Option<usize>
where
F: FnMut(&T, &T) -> bool,
{
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> bool>(
f: *const (),
a: *const u8,
b: *const u8,
) -> bool {
let f = unsafe { &mut *(f as *mut F) };
let a = unsafe { &*(a as *const T) };
let b = unsafe { &*(b as *const T) };
f(a, b)
}
unsafe {
let index = vec_find(
&raw const self.vec as *mut _,
elem as *const T as *const u8,
cmp_trampoline::<T, F>,
&raw mut cmp as *mut F as *mut (),
);
if index == usize::MAX {
None
} else {
Some(index)
}
}
}
fn binary_search_by<F>(&self, elem: &T, mut cmp: F) -> Result<usize, usize>
where
F: FnMut(&T, &T) -> i32,
{
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> i32>(
f: *const (),
a: *const u8,
b: *const u8,
) -> i32 {
let f = unsafe { &mut *(f as *mut F) };
let a = unsafe { &*(a as *const T) };
let b = unsafe { &*(b as *const T) };
f(a, b)
}
unsafe {
let (index, vacant) = vec_binary_search_by(
&raw const self.vec as *mut _,
elem as *const T as *const u8,
cmp_trampoline::<T, F>,
&raw mut cmp as *mut F as *mut (),
);
if vacant {
Err(index)
} else {
Ok(index)
}
}
}
fn insert_sorted<F>(&self, elem: T, mut cmp: F) -> Result<usize, usize>
where
F: FnMut(&T, &T) -> i32,
{
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> i32>(
f: *const (),
a: *const u8,
b: *const u8,
) -> i32 {
let f = unsafe { &mut *(f as *mut F) };
let a = unsafe { &*(a as *const T) };
let b = unsafe { &*(b as *const T) };
f(a, b)
}
let mut elem = core::mem::ManuallyDrop::new(elem);
unsafe {
let (index, inserted) = vec_insert_sorted(
&raw const self.vec as *mut _,
&raw const elem as *const u8,
cmp_trampoline::<T, F>,
&raw mut cmp as *mut F as *mut (),
);
Ok(index)
}
}
}
#[unsafe(no_mangle)]
extern "C" fn panic() -> ! {
panic!("Called panic from external code.");
}
unsafe impl Send for BlobVec {}
unsafe impl Sync for BlobVec {}
unsafe extern "C" {
unsafe fn vec_init(vec: *mut BlobVec, elem_size: usize, drop: Option<extern "C" fn(*mut u8)>);
unsafe fn vec_init_with(
vec: *mut BlobVec,
elem_size: usize,
drop: Option<extern "C" fn(*mut u8)>,
cap: usize,
);
unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8);
unsafe fn vec_insert(vec: *mut BlobVec, index: usize, elem: *const u8);
unsafe fn vec_pop(vec: *mut BlobVec);
unsafe fn vec_drop_last(vec: *mut BlobVec);
unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8;
#[allow(dead_code)]
unsafe fn vec_remove(vec: *mut BlobVec, index: usize);
#[allow(dead_code)]
unsafe fn vec_drop(vec: *mut BlobVec);
unsafe fn vec_find(
vec: *mut BlobVec,
elem: *const u8,
cmp: extern "C" fn(*const (), *const u8, *const u8) -> bool,
cmp_data: *mut (),
) -> usize;
unsafe fn vec_binary_search_by(
vec: *mut BlobVec,
elem: *const u8,
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
cmp_data: *mut (),
) -> (usize, bool);
unsafe fn vec_insert_sorted(
vec: *mut BlobVec,
elem: *const u8,
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
cmp_data: *mut (),
) -> (usize, bool);
}
fn main() { fn main() {
static mut DROPS: usize = 1; static mut DROPS: usize = 1;
@ -318,7 +62,7 @@ fn main() {
eprintln!("Push/pop test passed\n"); eprintln!("Push/pop test passed\n");
} }
let mut vec = VecT::<u32>::new_with(100); let mut vec = Vec::<u32>::new_with(100);
assert_eq!(vec.len(), 0); assert_eq!(vec.len(), 0);
vec.push(10); vec.push(10);
vec.push(20); vec.push(20);
@ -358,6 +102,6 @@ fn main() {
assert_eq!(vec.binary_search_by(&5, cmp), Err(0)); assert_eq!(vec.binary_search_by(&5, cmp), Err(0));
assert_eq!(vec.binary_search_by(&55, cmp), Err(4)); assert_eq!(vec.binary_search_by(&55, cmp), Err(4));
vec.insert_sorted(35, cmp); _ = vec.insert_sorted(35, cmp);
assert_eq!(vec.as_slice(), &[20, 30, 35, 40, 50]); assert_eq!(vec.as_slice(), &[20, 30, 35, 40, 50]);
} }