fluffy_hub

joined 10 months ago
[–] fluffy_hub@programming.dev 1 points 4 months ago* (last edited 4 months ago) (1 children)

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 :)

 

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 _) }
    }
}
[–] fluffy_hub@programming.dev 2 points 4 months ago* (last edited 4 months ago) (3 children)

Here is an update. I focused on the Node which is the smallest element of the buffer, it is what contains any meta data and the data payload. The code is heavily reduced but what is shared is pretty much verbatim maybe some minor edits

Update on the Node for my allocator

[–] fluffy_hub@programming.dev 1 points 4 months ago

Yes a Global Allocator to be used with the GlobalAlloc trait

 

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

[–] fluffy_hub@programming.dev 1 points 6 months ago

Thank you I did check but unfortunately and i'm soprry to report it didn't resolve the issue. I've contacted the manufacturer for further support support.

1
submitted 6 months ago* (last edited 6 months ago) by fluffy_hub@programming.dev 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

[–] fluffy_hub@programming.dev 1 points 8 months ago (1 children)

Do you often attempt to but fail to deduct things, you don't have the skills to perform, or is this a first?

[–] fluffy_hub@programming.dev 2 points 9 months ago (3 children)
[–] fluffy_hub@programming.dev 2 points 9 months ago

I have came accress WGPU. But my goal is to write as close to the OS and other API's as possible. So i will probably go with Vulkan natively but thanks for the idea!!

[–] fluffy_hub@programming.dev 1 points 9 months ago

I have considered it in the past but JSON feels like the standard. But TOML could be an option. I might try to see which I like better

[–] fluffy_hub@programming.dev 0 points 9 months ago (5 children)

Your not being rude. You are just wrong, I watched it twice once before you posted when the video was about 6 minutes old, and again when you posted it. I just confirmed that it isn't a new C.

[–] fluffy_hub@programming.dev 5 points 9 months 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

[–] fluffy_hub@programming.dev 4 points 9 months ago (1 children)

I've been meaning to try Gleam, I hear really good things about it. Maybe I can make a Gleam-like scripting language for my game-engine.

45
submitted 9 months ago* (last edited 9 months ago) by fluffy_hub@programming.dev to c/rust@programming.dev
 

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 🏳️‍⚧️

 

I'm currently suffering a dilemma and I’m considering using Odin over Rust.

I was hoping for friendly and positively constructive assessments of which language and why from anyone who wishes to answer?

view more: next ›