diff --git a/lang/tests/shared/shared.rs b/lang/tests/shared/shared.rs index ce87f4c..091e770 100644 --- a/lang/tests/shared/shared.rs +++ b/lang/tests/shared/shared.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + #[unsafe(no_mangle)] extern "C" fn panic() -> ! { panic!("Called panic from external code."); @@ -31,10 +33,297 @@ impl MaybeFFISlice { } impl FFISlice { - pub fn as_slice(&self) -> &[u8] { + pub unsafe fn as_slice(&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) } } - pub fn as_str(&self) -> &str { - unsafe { core::str::from_utf8_unchecked(self.as_slice()) } + pub unsafe fn as_str(&self) -> &str { + 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, +} + +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 { + pub vec: BlobVec, + _marker: core::marker::PhantomData, + } + + impl Vec { + 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(ptr: *mut u8) { + unsafe { + core::ptr::drop_in_place::(ptr as *mut T); + } + } + + unsafe { + vec_init_with( + &mut vec, + core::mem::size_of::(), + Some(drop_fn::), + capacity, + ); + } + + Self { + vec, + _marker: core::marker::PhantomData, + } + } + + pub fn as_slice(&self) -> &[T] { + assert_eq!(self.vec.elem_size, core::mem::size_of::()); + 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::()); + 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 { + 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(&self, elem: &T, mut cmp: F) -> Option + where + F: FnMut(&T, &T) -> bool, + { + extern "C" fn cmp_trampoline 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::, + &raw mut cmp as *mut F as *mut (), + ); + if index == usize::MAX { + None + } else { + Some(index) + } + } + } + + pub fn binary_search_by(&self, elem: &T, mut cmp: F) -> Result + where + F: FnMut(&T, &T) -> i32, + { + extern "C" fn cmp_trampoline 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::, + &raw mut cmp as *mut F as *mut (), + ); + if vacant { + Err(index) + } else { + Ok(index) + } + } + } + + pub fn insert_sorted(&self, elem: T, mut cmp: F) -> Result + where + F: FnMut(&T, &T) -> i32, + { + extern "C" fn cmp_trampoline 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::, + &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, + ); + pub unsafe fn vec_init_with( + vec: *mut BlobVec, + elem_size: usize, + drop: Option, + 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); } } diff --git a/lang/tests/tokens.rs b/lang/tests/tokens.rs index 8c594cb..c96102b 100644 --- a/lang/tests/tokens.rs +++ b/lang/tests/tokens.rs @@ -18,12 +18,6 @@ impl PartialEq for Lexeme { impl Eq for Lexeme {} -impl Lexeme { - fn lex(&self) -> &'static str { - self.1 - } -} - trait AsLexeme { fn as_lexeme(self) -> Option; } diff --git a/lang/tests/vec.rs b/lang/tests/vec.rs index 282b53f..8c83d0f 100644 --- a/lang/tests/vec.rs +++ b/lang/tests/vec.rs @@ -1,263 +1,7 @@ -#[repr(C)] -pub struct BlobVec { - pub data: *mut u8, - pub len: usize, - pub cap: usize, - pub elem_size: usize, - pub drop: Option, -} +#[path = "shared/shared.rs"] +mod util; -struct VecT { - vec: BlobVec, - _marker: core::marker::PhantomData, -} - -impl VecT { - 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(ptr: *mut u8) { - unsafe { - core::ptr::drop_in_place::(ptr as *mut T); - } - } - - unsafe { - vec_init_with( - &mut vec, - core::mem::size_of::(), - Some(drop_fn::), - capacity, - ); - } - - Self { - vec, - _marker: core::marker::PhantomData, - } - } - - fn as_slice(&self) -> &[T] { - assert_eq!(self.vec.elem_size, core::mem::size_of::()); - 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::()); - 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 { - 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(&self, elem: &T, mut cmp: F) -> Option - where - F: FnMut(&T, &T) -> bool, - { - extern "C" fn cmp_trampoline 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::, - &raw mut cmp as *mut F as *mut (), - ); - if index == usize::MAX { - None - } else { - Some(index) - } - } - } - - fn binary_search_by(&self, elem: &T, mut cmp: F) -> Result - where - F: FnMut(&T, &T) -> i32, - { - extern "C" fn cmp_trampoline 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::, - &raw mut cmp as *mut F as *mut (), - ); - if vacant { - Err(index) - } else { - Ok(index) - } - } - } - - fn insert_sorted(&self, elem: T, mut cmp: F) -> Result - where - F: FnMut(&T, &T) -> i32, - { - extern "C" fn cmp_trampoline 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::, - &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); - unsafe fn vec_init_with( - vec: *mut BlobVec, - elem_size: usize, - drop: Option, - 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); -} +use util::{ffi::*, vec::Vec, BlobVec}; fn main() { static mut DROPS: usize = 1; @@ -318,7 +62,7 @@ fn main() { eprintln!("Push/pop test passed\n"); } - let mut vec = VecT::::new_with(100); + let mut vec = Vec::::new_with(100); assert_eq!(vec.len(), 0); vec.push(10); 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(&55, cmp), Err(4)); - vec.insert_sorted(35, cmp); + _ = vec.insert_sorted(35, cmp); assert_eq!(vec.as_slice(), &[20, 30, 35, 40, 50]); }