[–] [S] 1 point 11 months ago* (last edited 11 months ago) (1 child)

Ah, got it—let me clarify a bit.

Right now, I’m working with arrays and slicing them into smaller segments for indexing. Technically, I could rely on bit manipulation to generate much of this, but I’ve chosen to lean into Rust’s type system for that extra layer of expressive control.

In Rust, a slice is essentially a fat pointer: it includes both a memory address and a length. Because the slice type encapsulates both, I don’t need to manually track sizes or offsets. Plus, in debug builds, Rust automatically panics if I try to access an out-of-bounds index, which helps catch issues early. And I can use methods like get or get_mut for safe, optional access—either retrieving a value or returning None.

Ultimately, Rust's type system saves me from fiddling with raw bit arithmetic and length bookkeeping. It handles validation elegantly, letting me focus on logic instead of low-level guards.

PS: Although it isn't finished just yet, I'm linking this Node up with a Buf and Slab struct currently. If i remember when I've completed the design and I'm happy to freely distribute the code, I'll make a paste bin and post it here for you. Always happy to help if I can :)

  • source
  • parent
  • context
  •  

    After sketching a few designs and digging into Rust Atomics and Locks: Low-Level Concurrency in Practice by Mara Bos, I’ve finally locked down the Node component of the allocator.

    The Node represents the smallest memory unit the allocator operates on. It holds the pointer to the memory chunk to be handed out.

    I’ve benchmarked this at around 200 nanoseconds, compared to 2000+ nanoseconds for Windows’ HeapAlloc. By bypassing a context switch on my machine, the Node allocation logic gives a 10× speed-up, which is huge.

    This is the only finalized part so far, but I’ll update benchmarks as other components come together. There’s still more testing to do and more structs to define for broader allocator functionality.

    For now, I’m sharing a full screenshot of this section of code. The project is proprietary (not something I intend to police) if someone replicates it, but because of that, I won’t be publishing the complete codebase. Future examples will lean illustrative rather than literal.

    That being said this isn’t the code verbatim either but it’s a lot of it and gives the whole mechanics of how a node allocates data and tracks meta. Hope this helps others ❤️

    #[derive(Debug)]
    pub struct Node<const HEADER_LEN: usize, const DATA_LEN: usize, const BUFFER_LEN: usize> {
        header: [u8; HEADER_LEN],
        data: [u8; DATA_LEN],
    }
    
    impl<const HEADER_LEN: usize, const DATA_LEN: usize, const BUFFER_LEN: usize>
        Node<HEADER_LEN, DATA_LEN, BUFFER_LEN>
    {
        #[inline]
        pub fn write_header_info_ptr<P>(
            &mut self,
            position_begin_as_usize: usize,
            type_as_ptr: *const P,
        ) -> usize {
            let position_end_as_usize = position_begin_as_usize + SYS_POINTER_WIDTH;
            let type_as_usize = type_as_ptr as usize;
            let type_as_byte_array = type_as_usize.to_ne_bytes();
            let type_as_byte_slice = type_as_byte_array.as_slice();
            let writable_header_section =
                &mut self.header[position_begin_as_usize..position_end_as_usize];
    
            writable_header_section.copy_from_slice(type_as_byte_slice);
            position_end_as_usize
        }
    
        #[inline(always)]
        pub fn read_header_info_ptr<P>(&self, position_begin_as_usize: usize) -> (usize, NonNull<P>) {
            let position_end_as_usize = position_begin_as_usize + SYS_POINTER_WIDTH;
            let readable_header_section = &self.header[position_begin_as_usize..position_end_as_usize];
            let mut result_buf = [0u8; SYS_POINTER_WIDTH];
    
            result_buf.copy_from_slice(readable_header_section);
    
            let addr = usize::from_ne_bytes(result_buf);
            let type_as_ptr = addr as *const P;
    
            (position_end_as_usize, unsafe {
                NonNull::new_unchecked(type_as_ptr as *mut P)
            })
        }
    
        pub fn aligned_addr(&mut self, align: usize) -> Option<NonNull<u8>> {
            let data_as_mut_ptr = self.data.as_mut_ptr();
            let word_offset_as_mut_ptr = unsafe { data_as_mut_ptr.add(SYS_POINTER_WIDTH) };
    
            let align_offset = word_offset_as_mut_ptr.align_offset(align);
            let align_offset_as_mut_ptr = unsafe { word_offset_as_mut_ptr.add(align_offset) };
    
            unsafe {
                let header_as_ptr = &self.header as *const [u8; HEADER_LEN];
                let header_as_usize = header_as_ptr as usize;
                let header_as_byte_array = header_as_usize.to_ne_bytes();
                let header_as_byte_slice = header_as_byte_array.as_slice();
                let write_header = align_offset_as_mut_ptr.sub(SYS_POINTER_WIDTH) as *mut u8;
                let write_buf = slice::from_raw_parts_mut(write_header, SYS_POINTER_WIDTH);
    
                write_buf.copy_from_slice(header_as_byte_slice);
            }
    
            NonNull::new(align_offset_as_mut_ptr)
        }
    
        pub fn resolve_addr(
            position_begin_as_usize: usize,
            ptr: *mut u8,
            head: *mut Self,
        ) -> NonNull<Self> {
            let position_end = SYS_POINTER_WIDTH + position_begin_as_usize;
            let header_as_ptr = unsafe { ptr.sub(SYS_POINTER_WIDTH) };
            let header_as_slice = unsafe { slice::from_raw_parts(header_as_ptr, SYS_POINTER_WIDTH) };
            let mut header_as_array = [0u8; SYS_POINTER_WIDTH];
    
            header_as_array.copy_from_slice(header_as_slice);
    
            let header_as_usize = usize::from_ne_bytes(header_as_array);
            let header_as_mut_ptr = header_as_usize as *mut [u8; HEADER_LEN];
            let header_as_slice = unsafe { &*header_as_mut_ptr };
            let node_as_slice = &header_as_slice[position_begin_as_usize..position_end];
            let mut node_buf_array = [0u8; SYS_POINTER_WIDTH];
    
            node_buf_array.copy_from_slice(node_as_slice);
    
            let node_as_usize = usize::from_ne_bytes(node_buf_array);
            let node_as_ptr = node_as_usize as *const Self;
    
            unsafe {
                let head_as_usize = head as usize;
                let head_as_byte_array = head_as_usize.to_ne_bytes();
                let head_as_byte_slice = head_as_byte_array.as_slice();
                let header_as_mut_ref = &mut *header_as_mut_ptr;
                let header_first_word_as_mut_slice =
                    &mut header_as_mut_ref[SYS_POINTER_WIDTH * 7..SYS_POINTER_WIDTH * 8];
    
                header_first_word_as_mut_slice.copy_from_slice(head_as_byte_slice);
            }
    
            unsafe { NonNull::new_unchecked(node_as_ptr as *mut _) }
        }
    }
    
     

    So I've been writing an allocator. A difficult task and in Rust it is currently a dream to write.

    The patterns I'm on about are small quick scopes to get a mutable reference and store or read data.

    pub fn some_func(&mut self, s: &[u8]) {
        // Mutable borrow 1 and write
        {
            let writable = &mut self.buf[..8];
    
            writable[..8].copy_from_slice();
        }
    
        // Mutable borrow 2 and write
        {
            let writable = &mut self.buf[8..16];
    
            writable[8..16].copy_from_slice();
        }
    
        // And so on . . .
    }
    

    No other language feels like this. No other language is so precise on reads and writes always taking a length or the length can be obtained from the type (such as a slice).

    Writing to different parts of a buffer and selecting parts of like this feels amazing. For writing an allocator i can just make array's and then write any bytes to them and just read them back and cast them about.

    So much better than just using raw pointers, and safer as sizes are usually know with slices.

    Anyway i just love Rust and this was an excuse to share my love of Rust <3

    submitted 1 year ago* (last edited 1 year ago) by to c/linuxhardware@programming.dev
     

    The ATH12K driver is unstable for use with the Qualcomm FastConnect 7800 Wi-Fi 7 High Band Simultaneous (HBS) Network Adapter.

    It will break it eventually and if you switch back over to Windows (ew) then you will find the Windows HBS side of you WiFi doesn't work essentially making it a WiFi-6 module and not a WiFi-7 module as the 5G signal will sill work.

    I blocked the person below so i can no longer see their comment which offered no help at all and was completely useless. However, a lovely person did comment saying i think i needed the Windows 11 Version 24H2 for x64-based Systems. This information which they provided is correct. You need to update to the KB5058499 update.

    Once install you must go the Settings -> Network & Internet -> Advanced network settings -> Network reset. Then click on Reset now button and it will restore the original firm back on to the module. After the restart the module should work as expected.

    Edit: This is a complete revamp of the post because i was high as hell when i originally wrote it. I hope this provide more clarity on the situation and details. Have a good day <3

    [–] 6 points 1 year ago (7 children)

    I saw this the other day. After clicking your link i left a comment but essentially Rust is Rust, it's more that C/C++ is at the end of its life. But i get the title aiming to mean Rust is taking over C's role, Rust is a completely differnt beast

  • source
  •  

    Hello,

    This is my first post to this Rust community and I am happy to introduce myself and discuss what I love about this language, but first a little about myself.

    I'm Alice, Fluffy to most, and she/her are my pronouns. I'm from the UK. I got a little boy who love like crazy. I'm Autistic, suffer from cPTSD and I also 🩷 Rust!!

    Rust I feel appeals to Autistic people because of it's focus on accuracy and correctness. It's a common feeling people have about the language. But as the type of person I am I love it.

    I began learning it in 2023, before this I was using C++. Rust showed me the importance of error's as values and helped improve the quality of my code.

    Currently I'm writing a game-engine as a hobby. The game-engine is a work in progress (WIP) and I have only just begun it's development. Since the game-engine will natively support various platforms. To ensure consistency I'm writing all the platform specific code manually and building my own custom standard library for my engine, loosely based on the actual Rust standard library.

    Right now I have the code in place to create/remove directories and to create, delete, write, read and set file pointer location. Convert UTF8 to UTF16 and output to the console in Unicode (Windows C API uses UTF16) and heap functions to get the process heap and create and delete memory dynamically.

    Next will be the 'config.json' for which Serde will be used. Then the logger, and so on.

    So it is a WIP but it's fun and given my conditions allows me to do what I love, writing Rust code.

    Thanks for reading!!

    Alice 🏳️‍⚧️

    view more: next ›