How to get a half edge implementation that is sane? - data-structures

I have been fighting the borrow checker and undefined behavior for days now and I am frustrated.
There is a data structure called a half edge (also known as a doubly connected edge list), if you do not know what that is please watch this or see this page to understand what this is about.
I have implemented this multiple times in C++, in that language I use the following interface:
edge.next()
face.edge()
vert.edge()
and so on, to access elements. note 2 things. 1 you are accessing elements through the facets, not the mesh, 2 no explicit referencing to the enclosing mesh data structure exists.
This is the ideal interface, it;s simple, it's readable. The following are other potential interfaces that I abhor, they are stupid, cumbersome, terrible and no sane human should be subjected to them:
mesh.hedges[edge_id]
mesh.get_edge(edge_id)
Why? well let's say you wanted to do edge.next().next().next() with the above. We would get:
mesh.get_edge(mesh.get_edge(mesh.get_edge(id).next_id).next_id)
Clearly unreadable, to make it work it would need to be:
id1 = mesh.get_edge(id).next_id
id2 = mesh.get_edge(id1).next_id
mesh.get_edge(id2)
This is at least readable, but we achieved in 3 lines and a whole bunch of characters something that could be achieved in a one liner. There's also way more thinking involved, it taxes the brain of the user. We consider the users brain to be a valuable resource that should never be burdened with nonsense.
With this in min, I tried using unsafe code to make something like this work:
pub struct HEdge<'a, V, E, F>
where
V: Clone,
E: Clone,
F: Clone,
{
pub(crate) id: GeomId,
pub(crate) next_id: GeomId,
pub(crate) prev_id: GeomId,
pub(crate) pair_id: GeomId,
pub(crate) vert_id: GeomId,
pub(crate) face_id: GeomId,
pub data: E,
pub(crate) mesh: *mut HalfMesh<'a, V, E, F>,
}
impl<'a, V, E, F> HEdge<'a, V, E, F>
where
V: Clone,
E: Clone,
F: Clone,
{
pub fn next_mut(&self) -> &mut HEdge<'a, V, E, F>
{
unsafe {
debug_assert!(self.next_id != ABSENT);
debug_assert!(usize::from(self.next_id) < (*self.mesh).hedges.len());
&mut (*self.mesh).hedges[usize::from(self.next_id)]
}
}
}
And this is an example usage (that segfaults):
pub fn split(&mut self) -> &mut Vert<'a, V, E, F>
{
unsafe {
let v2_id = self.pair().prev().source().id;
let v3_id = self.dest().id;
let v4_id = self.prev().source().id;
let vn_id = (*self.mesh).add_vert(self.source().data.clone());
let e1_id = self.id;
let e2_id = self.pair().id;
let e3_id = self.next().id;
let e4_id = self.prev().id;
let e5_id = self.pair().next().id;
let e6_id = self.pair().prev().id;
let (e7_id, e8_id) =
(*self.mesh).add_edge(vn_id, v2_id, self.data.clone(), self.data.clone());
let (e9_id, e10_id) =
(*self.mesh).add_edge(v4_id, vn_id, self.data.clone(), self.data.clone());
println!("{}", (*self.mesh).hedges.len());
let (e11_id, e12_id) =
(*self.mesh).add_edge(v3_id, vn_id, self.data.clone(), self.data.clone());
let f1_id = self.face_id;
let f2_id = self.pair().face_id;
let f3_id = (*self.mesh).add_face(e10_id, self.face().data.clone());
let f4_id = (*self.mesh).add_face(e8_id, self.pair().face().data.clone());
attach_face(
&mut (*self.mesh).faces[f1_id.0 as usize],
&mut (*self.mesh).hedges[e1_id.0 as usize],
&mut (*self.mesh).hedges[e3_id.0 as usize],
&mut (*self.mesh).hedges[e9_id.0 as usize],
);
attach_face(
&mut (*self.mesh).faces[f2_id.0 as usize],
&mut (*self.mesh).hedges[e2_id.0 as usize],
&mut (*self.mesh).hedges[e7_id.0 as usize],
&mut (*self.mesh).hedges[e6_id.0 as usize],
);
attach_face(
&mut (*self.mesh).faces[f3_id.0 as usize],
&mut (*self.mesh).hedges[e10_id.0 as usize],
&mut (*self.mesh).hedges[e4_id.0 as usize],
&mut (*self.mesh).hedges[e11_id.0 as usize],
);
attach_face(
&mut (*self.mesh).faces[f4_id.0 as usize],
&mut (*self.mesh).hedges[e8_id.0 as usize],
&mut (*self.mesh).hedges[e12_id.0 as usize],
&mut (*self.mesh).hedges[e5_id.0 as usize],
);
return &mut (*self.mesh).verts[vn_id.0 as usize];
}
Well this design is utterly broken. It triggers UB left and right, it doesn't work, it;s bad, it's terrible.
I have scouted the internet, tried multiple hacks and different things. I cannot, for the life of me, find a way to get rust working the way this api works in C++, that is, to get
edge.next() as a method with no UB, segfaults or compilation errors.
Every suggestion people give me results in basically mesh.get_edge(id), which we established is bad.
This code was an attempt at adapting some C++ code that has been battle tested for 3 years that provides that API. How do I achieve this in rust? i.e. how do I make a struct Mesh and struct Edge, such that edge references mesh under the hood and allows me to do edge.next() without UB or runtime errors?
For further context and the curious this is the implementation atm, but as mentioned this is a broken design.

Related

How to use SetDisplayConfig (windows-rs) to force screen re-detection?

I am using windows-rs (Latest version from GitHub, because it contains some fixes the stable version on Crates.io doesn't have).
My goal is to develop a small software that automatically forces the screen to be re-detected and set to the highest resolution (It's for a school with a weird setup where teachers have to turn projectors on before the PC for resolutions to get detected, but often forget that, leading the PCs to have a very low resolution, and the higher resolutions not being detected).
For re-initializing the screen, I have the following function:
// Some imports may be unused here, I haven't checked them yet, the full file has more functions
use windows::Win32::Graphics::Gdi::{ChangeDisplaySettingsA, EnumDisplaySettingsA, DEVMODEA, SDC_FORCE_MODE_ENUMERATION, SDC_APPLY, SDC_SAVE_TO_DATABASE, SDC_USE_SUPPLIED_DISPLAY_CONFIG, QDC_ALL_PATHS};
use windows::Win32::Media::Audio::Endpoints::IAudioEndpointVolume;
use windows::Win32::Media::Audio::{IMMDeviceEnumerator, MMDeviceEnumerator};
use windows::Win32::Devices::Display::{GetDisplayConfigBufferSizes, QueryDisplayConfig, SetDisplayConfig, DISPLAYCONFIG_TOPOLOGY_ID};
use windows::core::GUID;
use windows::Win32::System::Com::{CoInitialize, CoCreateInstance, CLSCTX_ALL};
// Forces Windows to reinit display settings
pub fn force_reinit_screen() -> i32 {
let mut path_count = 0;
let mut mode_count = 0;
let result = unsafe { GetDisplayConfigBufferSizes(QDC_ALL_PATHS, &mut path_count, &mut mode_count) };
println!("GetDisplayConfigBufferSizes returned {}", result);
let mut path_array = Vec::with_capacity(path_count as usize);
let mut mode_array = Vec::with_capacity(mode_count as usize);
let result = unsafe {
QueryDisplayConfig(
QDC_ALL_PATHS,
&mut path_count,
path_array.as_mut_ptr(),
&mut mode_count,
mode_array.as_mut_ptr(),
::core::mem::transmute(::core::ptr::null::<DISPLAYCONFIG_TOPOLOGY_ID>()),
)
};
println!("QueryDisplayConfig returned {}", result);
let flags = SDC_FORCE_MODE_ENUMERATION | SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_SAVE_TO_DATABASE;
let result = unsafe { SetDisplayConfig(Some(&path_array), Some(&mode_array), flags) };
result
}
However, it does not work on any computer I've tried this on (Returns code 87, which seems to mean bad parameters). What am I doing wrong?

Trying to Read Process Memory with windows_sys::Win32::System::Diagnostics::Debug::ReadProcessMemory in rust

I'm trying to read health in rust from a game called Assault cube.
However i allways have 0 stored in buffer. can anyone explain what i´m doing wrong?
my code looks like this:
fn main(){
unsafe{
use std::ffi::c_void;
use windows_sys::Win32::Foundation::HANDLE;
let process_id:HANDLE = 13488;
let health_adress = 0x005954FC as *const c_void;
let buffer: *mut c_void = std::ptr::null_mut();
let mut number_read:usize= 0;
windows_sys::Win32::System::Diagnostics::Debug::ReadProcessMemory(process_id, health_adress, buffer,4 , &mut number_read);
println!("{:?}", buffer as i32);
}
}
the picture below shows how I got the address with Cheat Engine.

Windows, add user by Rust

I use winapi NetUserAdd to add a user,account added succsess,execute command net user,shows as below picture and cannot find users by control panel.
What wrong with LPSWTR or USER_INFO_1 struct to LPBYTE?
use winapi::um::lmaccess::{USER_INFO_1,NetUserAdd,UF_SCRIPT};
use std::iter::{once};
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;
pub fn winstr(value: &str) -> Vec<u16> {
OsStr::new(value).encode_wide().chain(once(0)).collect()
}
fn main() {
let username:String = "Test".to_string();
let password:String = "Test******".to_string();
let mut user = USER_INFO_1{
usri1_name:winstr(&username).as_mut_ptr(),
usri1_password:winstr(&password).as_mut_ptr(),
usri1_priv:1,
usri1_password_age: 0,
usri1_home_dir: std::ptr::null_mut(),
usri1_comment: std::ptr::null_mut(),
usri1_flags:UF_SCRIPT,
usri1_script_path: std::ptr::null_mut(),
};
let mut error = 0 ;
unsafe{
NetUserAdd(std::ptr::null_mut(),1,&mut user as *mut _ as _,&mut error);
}
println!("{}",error);//result is 0,means success.
}
You're sending dangling pointers.
Your winstr(...).as_mut_ptr() calls create a Vec<u16>, gets a pointer to its data, and drops the Vec<u16> since it was a temporary value. You need to keep those values at least until the call to NetUserAdd has finished:
let mut username = winstr("Test");
let mut password = winstr("Test******");
let mut user = USER_INFO_1{
usri1_name: username.as_mut_ptr(),
usri1_password: password.as_mut_ptr(),
usri1_priv: 1,
usri1_password_age: 0,
usri1_home_dir: std::ptr::null_mut(),
usri1_comment: std::ptr::null_mut(),
usri1_flags: UF_SCRIPT,
usri1_script_path: std::ptr::null_mut(),
};

How to create a subscription for events in Windows using Rust and the winapi crate?

I'm trying to subscribe to Windows events using EvtSubscribe from the winapi crate, but I'm getting ERROR_INVALID_PARAMETER.
I can not find an example in Rust, but did find a C++ example.
My code that produces ERROR_INVALID_PARAMETER:
fn main() {
unsafe {
let mut callback: winapi::um::winevt::EVT_SUBSCRIBE_CALLBACK = None;
let mut session = std::ptr::null_mut();
let mut signal_event = std::ptr::null_mut();
let mut bookmark = std::ptr::null_mut();
let mut context = std::ptr::null_mut();
let channel_path = "Security";
let channel_path: winnt::LPWSTR = to_wchar(channel_path);
let query = "Event/System[EventID=4624]";
let query: winnt::LPWSTR = to_wchar(query);
let event_handle = winevt::EvtSubscribe(
session,
signal_event,
channel_path,
query,
bookmark,
context,
callback,
winevt::EvtSubscribeStartAtOldestRecord,
);
//println!("{:?}", &event_handle);
println!("{:?}", &winapi::um::errhandlingapi::GetLastError());
} //unsafe end
}
fn to_vec(str: &str) -> Vec<u16> {
return OsStr::new(str)
.encode_wide()
.chain(Some(0).into_iter())
.collect();
}
fn to_wchar(str: &str) -> *mut u16 {
return to_vec(str).as_mut_ptr();
}
The documentation for EvtSubscribe states:
SignalEvent
[...] This parameter must be NULL if the Callback parameter is not
NULL.
Callback
[...] This parameter must be NULL if the SignalEvent parameter is
not NULL.
The unstated implication here is that exactly one of these parameters must be provided. Passing both is explicitly disallowed, but passing neither would not make sense, as otherwise there would be no way for your code to receive the event.
Passing one of these values should cause the code to start working.
Editorially, this is a good example of where a Rust enum would have been a better way to model the API. This would clearly show that the two options are mutually exclusive and one is required:
enum Subscriber {
EventObject(HANDLE),
Callback(EVT_SUBSCRIBE_CALLBACK),
}
Incidentally, your implementation of to_wchar is incorrect and likely leads to memory unsafety. to_vec allocates memory, you take a pointer to it, then that memory is deallocated, creating a dangling pointer. The bad pointer is read by the C code inside of the unsafe block — part of the reason unsafe is needed.
You either need to use mem::forget, as shown in How to expose a Rust `Vec<T>` to FFI? (and then you need to prevent leaking the memory somehow), or you need to take a reference to the data instead of taking the raw pointer.

Safely return multiple references to internal nodes, while still allowing mutation of other nodes

Suppose, for example, I have a linked list which does not allow removal of nodes.
Would it be possible to return shared references to values which have already been inserted, while still allowing the relative order of the nodes to be changed, or new nodes inserted?
Even mutation through one of the nodes should be safe "on paper" as long as only one node is used to mutate the list at a time. Is it possible to represent this in rust's ownership system?
I'm specifically interested in doing so without runtime overhead (potentially using unsafe in the implementation, but not in the interface).
EDIT: As requested, here is an example that gives the outline of what I am thinking of.
let list = MyLinkedList::<i32>::new()
let handle1 = list.insert(1); // Returns a handle to the inserted element.
let handle2 = list.insert(2);
let value1 : &i32 = handle1.get();
let value2 : &i32 = handle2.prev().get(); // Ok to have two immutable references to the same element.
list.insert(3); // Also ok to insert and swap nodes, while the references are held.
list.swap(handle1,handl2);
foo(value1,value2);
let exclusive_value: &mut i32 = handle1.get_mut(); // While this reference is held, no other handles can be used, but insertion and permutation are ok
handle5 = list.insert(4);
list.swap(handle1, handle2);
In other words, the data contained inside the nodes of the list is treated as one resource that can be borrowed shared/mutably, and the links between the nodes are another resource that can be borrowed shared/mutably.
In other words, the data contained inside the nodes of the list is treated as one resource that can be borrowed shared/mutably, and the links between the nodes are another resource that can be borrowed shared/mutably.
The idea to deal with such spatial partitioning is to introduce a different "key" for each partition; it's easy since they are static. This has been dubbed the PassKey pattern.
In the absence of brands, it will still require a run-time check: verifying that the elements-key is tied to this specific list instance is mandatory for safety. This is, however, a read-only comparison that will always be true, so the performance is about as good as it gets as far as run-time checks go.
The idea, in a nutshell:
let (handles, elements) = list.keys();
let h0 = handles.create(4);
handles.swap(h0, h1);
let e = elements.get(h0);
In your usecase:
It is always possible to change the links, so we will use internal mutability for this.
The borrow-check on elements inside handles will be carried out by borrowing elements.
The full implementation can be found here. It heavily uses unsafe, and I make no promise that it is fully safe, however it is hopefully sufficient for a demonstration.
In this implementation, I have opted for dumb handles and implemented the operations on the key types themselves. This limited the number of types who needed to borrow from the main list, and simplified borrowing.
The core idea, then:
struct LinkedList<T> {
head: *mut Node<T>,
tail: *mut Node<T>
}
struct Handles<'a, T> {
list: ptr::NonNull<LinkedList<T>>,
_marker: PhantomData<&'a mut LinkedList<T>>,
}
struct Elements<'a, T> {
list: ptr::NonNull<LinkedList<T>>,
_marker: PhantomData<&'a mut LinkedList<T>>,
}
LinkedList<T> will act as the storage, however will implement only 3 operations:
construction,
destruction,
handing out the keys.
The two keys Handles and Elements will both borrow the list mutably, guaranteeing that a single of (each of them) can exist simultaneously. Borrow-checking will prevent a new Handles or Elements from being created if any instance of them still lives for this list:
list: grants access to the list storage; Elements will only use it for checking (necessary) run-time invariants and never dereference it.
_marker: is the key to the borrow-checking actually guaranteeing exclusitivity.
Sounds cool so far? For completion, the last two structures then:
struct Handle<'a, T> {
node: ptr::NonNull<Node<T>>,
list: ptr::NonNull<LinkedList<T>>,
_marker: PhantomData<&'a LinkedList<T>>,
}
struct Node<T> {
data: T,
prev: *mut Node<T>,
next: *mut Node<T>,
}
Node is the most obvious representation of a doubly-linked list ever, so we're doing something right. The list in Handle<T> is there for the exact same purpose as the one in Elements: verifying that both Handle and Handles/Elements are talking about the same instance of list. It's critical for get_mut to be safe, and otherwise helps avoiding bugs.
There's a subtle reason for Handle<'a, T> having a lifetime tying to the LinkedList. I was tempted to remove it, however this would allow creating a handle from a list, destroying the list, then recreating a list at the same address... and handle.node would now be dangling!
And with, we only need to implement the methods we need on Handles and Elements. A few samples:
impl<'a, T> Handles<'a, T> {
pub fn push_front(&self, data: T) -> Handle<'a, T> {
let list = unsafe { &mut *self.list.as_ptr() };
let node = Box::into_raw(Box::new(Node { data, prev: ptr::null_mut(), next: list.head }));
unsafe { &mut *node }.set_neighbours();
list.head = node;
if list.tail.is_null() {
list.tail = node;
}
Handle {
node: unsafe { ptr::NonNull::new_unchecked(node) },
list: self.list, _marker: PhantomData,
}
}
pub fn prev(&self, handle: Handle<'a, T>) -> Option<Handle<'a, T>> {
unsafe { handle.node.as_ref() }.prev().map(|node| Handle {
node,
list: self.list,
_marker: PhantomData
})
}
}
And:
impl<'a, T> Elements<'a, T> {
pub fn get<'b>(&'b self, handle: Handle<'a, T>) -> &'b T {
assert_eq!(self.list, handle.list);
let node = unsafe { &*handle.node.as_ptr() };
&node.data
}
pub fn get_mut<'b>(&'b mut self, handle: Handle<'a, T>) -> &'b mut T {
assert_eq!(self.list, handle.list);
let node = unsafe { &mut *handle.node.as_ptr() };
&mut node.data
}
}
And this should be safe because:
Handles, after creating a new handle, only ever accesses its links.
Elements only ever returns references to data, and the links cannot be modified while it accesses them.
Example of usage:
fn main() {
let mut linked_list = LinkedList::default();
{
let (handles, mut elements) = linked_list.access();
let h0 = handles.push_front("Hello".to_string());
assert!(handles.prev(h0).is_none());
assert!(handles.next(h0).is_none());
println!("{}", elements.get(h0));
let h1 = {
let first = elements.get_mut(h0);
first.replace_range(.., "Hallo");
let h1 = handles.push_front("World".to_string());
assert!(handles.prev(h0).is_some());
first.replace_range(.., "Goodbye");
h1
};
println!("{} {}", elements.get(h0), elements.get(h1));
handles.swap(h0, h1);
println!("{} {}", elements.get(h0), elements.get(h1));
}
{
let (handles, elements) = linked_list.access();
let h0 = handles.front().unwrap();
let h1 = handles.back().unwrap();
let h2 = handles.push_back("And thanks for the fish!".to_string());
println!("{} {}! {}", elements.get(h0), elements.get(h1), elements.get(h2));
}
}

Resources