What's everyone working on this week (24/2026)?

New week, new Rust! What are you folks up to?

I am making Easel, a programming language that makes your game multiplayer automatically :slight_smile:

Working on DAGraph.com : analytics in the browser, canvas-based, reactive computation graph. No accounts needed. Data stays local. Still early, lots more features to be added, but looking for early feedback.

Some crates that it uses: Apache DataFusion, Apache Arrow, Apache OpenDAL, reactive_graph, Egui...

I am working on a phylogenetics software project. Very much beginner so learning has been great!

Implement a small Rust library for CLI rendering primitives - Oxink

Creating a bunch of tools to make my development smoother :]

Now creating tool where crash will not stop the app (there will special function to stop the app). Instead it will run the registered handler (eg returning error in the handler). The handler is not same for all, but can be different each other. Unlike Elixir, it will still within the same process for high performance. Also can handle external service failure differently, eg if database is down, the request data is saved to the disk with memmap and relative pointer that I already created in my tools collection above. Then after it detects the external service is up again, it retry the execution using the same data. So the app still able to accept new request not returning error, eventhough its internal service is down, that will be rerun asyncronously automatically, it will return response the request is accepted and is processed, only after some duration if the external service keep fails, then it stops retrying and run the registered handler (that can be code to return error). It is like message broker but embedded in the app, no network boundary. It is like the different of PostgreSQL and SQLite

I am thinking about a new "rusty" database language. It will have types a bit like Rust ( struct, enum ), a List (=Vec) type, a (hashed or sorted) Map type, and references ( which will be reference counted ). Values can be stored in pages (which are stored in the database file), a reference will be a page number + id within a page (56 bits in total). A Map is specified by a function which computes a key from a reference of a given type. A Map lookup operation returns a List of references (previously added to the map) which match the supplied key value.

sea_horse

Last week I programmed Cinefractal.

Cinefractal is a Python library in Rust for the generation, animation, and analysis of Escape Time Fractals.
It features the following technologies:

  • Rust and Rayon for fast parallel computation
  • pyo3, numpy, and maturin for the Python interface
  • pyo3 stub gen, sphinx, and autodoc 2 for stub and docu generation

This project pretty much spans the most extreme endings for the programming language range spectrum:

  • Rust: Efficient and safe language
  • Python: Easy and fast to prototype

It gives you an easy prototyping tool for animations of Escape Time Fractals (including Mandelbrot).

The GitHub link is here.
And the PyPI link here.

as the author of pyo3-stubgen · PyPI I got rather pleased for a moment, that this very dusty project of mine was valuable to someone. Then I noticed there is a similarly named rust crate you're using. Other than the clear advantage "part of the rust ecosystem", is there anything that lead you to choose one over the other? (as a tip to me if I feel like reviving and improving the python variant?)

Hi MusicalNinjaDad,

It was the first crate I found on crates.io, and it got the job done. It also covers classes and has a rather extensive documentation.

Take care,
Christoph

I'm generating some fractals to animated-svg (no rocket-science, just a bit of checking what is possible).
I do not paste the example images here to this discussion - may consume a bit of your browsers processing power :wink:
You may watch animated fractals at github: fernfarmforfun/README.md at main · awarnke/fernfarmforfun · GitHub
cu
Andi

I'm rewriting my (mostly) functional chess engine in Rust as an exercise to learn the language. Currently working on piece movement.

I've been working on my dependency-lite GUI calendar for Linux. No GUI toolkit, no browser. For rendering and windowing SDL is used. Perhaps I might even go without the standard library one day. I've implemented recently text selection and copying laladrik/Semana: A GUI calendar for GNU/Linux - Codeberg.org

I'm working on a log viewer that shows tracing spans as collapsible trees in a tree table.

I'm adapting the Rust code generation of my parser/lexer generator for bottom-up parsers. Almost there.

The code generation is by far the part I like less. :sweat_smile:

Bottom-up parsers are also so much less flexible than top-down parsers when it comes to adding features, due to their rightmost derivation nature. On the other hand, their core is relatively simple to make (at least for LALR–more reliable ones are harder).

Hi,I am working on a desktop app called Gittykat (just named by mixing git and cat). It is an offline tool to display information about a git repository with contribution graph, programming language analysis, and similar features. Built using iced GUI and gix to manage git. The above link will lead to the repository on Codeberg.

I started on some code for this:

use atom_file::Data;
use page_store::*;
use std::sync::Arc;

/// Set of working pages, clean and changed.
struct PageSet
{
    wapd: AccessPagedData,
    clean: HashMap<u64, Data>,
    changed: HashMap<u64, Data>,
}

impl PageSet
{
    fn new( wapd: AccessPagedData ) -> Self
    {
        Self { wapd, clean: HashMap::default(), changed: HashMap::default() }
    }

    fn new_page( &self ) -> u64
    {
        self.wapd.alloc_page() + 1 // Add 1 so that zero can be used as null page.
    }

    fn load( &mut self, pnum: u64 ) -> ( Data, bool )
    {
        if let Some(data) = self.clean.remove(&pnum) {
            ( data, false )
        } else if let Some(data) = self.changed.remove(&pnum) {
            ( data, true )
        }
        else {
            ( self.wapd.get_data( pnum - 1 ), false )
        }
    }
    
    fn note( &mut self, pnum: u64, data: Data, changed: bool )
    {
        if changed { self.changed.insert( pnum, data ); }
        else { self.clean.insert( pnum, data ); }
    }

    fn save( &mut self )
    {
        for (pnum, data) in self.changed.drain()
        {
           self.wapd.set_data(pnum-1, data);
        }
    }
}

/// Parent page is list of page numbers.
struct ParentPage
{
   data: Data,
}

impl ParentPage
{
    fn new() -> Self
    {
        Self{ data: Arc::new( Vec::new() ) }
    }
    
    fn from( data: Data ) -> Self
    {
        Self{ data }
    }
    
    fn take( self ) -> Data
    {
       self.data
    }

    /// Assign page number.
    fn assign(&mut self, ix: usize, pnum: u64)
    {
        let data = Arc::make_mut(&mut self.data);
        let off = ix * 8;
        let end = off + 8;
        if end > data.len()
        {
           data.resize( end, 0 );
        }
        let loc = &mut data[off..end];
        loc.copy_from_slice(&pnum.to_le_bytes());
    }

    /// Fetch page number.
    fn fetch(&self, ix: usize) -> u64
    {
        let off = ix * 8;
        let end = off + 8;
        if end > self.data.len() { return 0; }
        let loc = &self.data[off..end];
        u64::from_le_bytes(loc.try_into().unwrap())
    }
}

/// Byte Vector implemented as tree of pages.
///
/// root and len change as the TreeVec increases in size.
struct TreeVec<'a>
{
    root: u64,
    len: u64,
    ps: &'a mut PageSet,
    writing: bool,
    len_changed : bool,
    root_changed : bool,
}

impl <'a> TreeVec<'a>
{   
    /// Create a TreeVec to access contents( read/write ).
    pub fn new( root: u64, len: u64, ps: &'a mut PageSet ) -> Self
    {
        Self{ root, len, ps, writing: false, len_changed: false, root_changed: false }
    }

    /// Write bytes at specified index.
    pub fn write( &mut self, mut ix: u64, user_data: &[u8] )
    {
        self.writing = true;
        let mut todo = user_data.len();
        let levels = self.adjust_len( ix + todo as u64 );

        let mut done = 0;
        while todo > 0
        {
            let rpp = PAGE_SIZE;
            let mut pnum = self.root;
            if levels > 0
            {
                pnum = self.get_page( levels-1, pnum, ix / rpp );
                ix %= rpp;
            }

            let (mut data, _changed) = self.ps.load(pnum);
            let md = Arc::make_mut( &mut data);

            let off = ix as usize;
            let mut amount = PAGE_SIZE as usize - off;
            if amount > todo { amount = todo; }
            
            let end = off + amount;
            if end > md.len() { md.resize( end, 0 ); }
            let loc = &mut md[off..end];
            loc.copy_from_slice( &user_data[done..done+amount] );
            ix += amount as u64;
            done += amount;
            todo -= amount;
            self.ps.note(pnum, data, true);
        }
        self.writing = false;
    }

    /// Read bytes from specified index.
    ///
    /// If un-written bytes are detected, reading stops. Result is number of bytes read.
    /// However un-written bytes can also be read as zeroes. Often user_data is initialised to zero, so result is same.
    pub fn read( &mut self, mut ix: u64, user_data: &mut [u8]) -> usize
    {
        let mut todo = user_data.len();
        if ix + todo as u64 > self.len { return 0; }
        let levels = self.levels( self.len );

        let mut done = 0;
        while todo > 0
        {
            let rpp = PAGE_SIZE;
            let mut pnum = self.root;
            if levels > 0
            {
                pnum = self.get_page( levels-1, pnum, ix / rpp );
                if pnum == 0 { return done; }
                ix %= rpp;
            }
     
            let (data, changed) = self.ps.load(pnum);

            let off = ix as usize;
            let mut amount = PAGE_SIZE as usize - off;
            if amount > todo { amount = todo; }
            
            let end = off + amount;
            if end > data.len() { 
                return done;
            }
            let loc = &data[off..end];

            user_data[done..done+amount].copy_from_slice( loc );
            ix += amount as u64;
            done += amount;
            todo -= amount;
            self.ps.note(pnum, data, changed);
        }
        done
    }

    /// Get a page at specified level.
    fn get_page( &mut self, level: u8, mut page: u64, mut ix: u64 ) -> u64
    {
        let base = PAGE_SIZE / 8;
        if level > 1 {
            let x = ix / base;
            ix %= base;
            page = self.get_page(level - 1, page, x);
        }
        self.get_child_page( page, ix as usize)
    }

    /// Get a child page at specified index.
    fn get_child_page( &mut self, page: u64, ix: usize) -> u64
    {
        let (data, mut changed) = self.ps.load(page);
        let mut pp = ParentPage::from(data);
        let mut result = pp.fetch( ix );
        if result == 0
        {
           if !self.writing { return 0; }
           result = self.ps.new_page();
           pp.assign( ix, result );
           changed = true;
        }
        self.ps.note(page, pp.take(), changed);        
        result
    }

    /// Increase the TreeVec len to specified size, returns the number of levels.
    fn adjust_len( &mut self, size: u64 ) -> u8
    {
        let mut level = self.levels(self.len);
        if size > self.len 
        { 
            let new_level = self.levels(size);
            while level < new_level
            {
                self.inc_level();
                level += 1;
            }
            self.len = size;
            self.len_changed = true;
        }
        level
    }

    /// Increase the TreeVec level by creating a new root. The old root is stored in the new root at position 0.
    fn inc_level( &mut self )
    {
        let new_root = self.ps.new_page();
        let mut pp = ParentPage::new();
        pp.assign( 0, self.root );
        self.ps.note(new_root, pp.take(), true);
        self.root = new_root;
        self.root_changed = true;
    }

    /// Calculate number of extra levels needed for TreeVec of specified size.
    fn levels(&self, size: u64) -> u8
    {
        let rpp = PAGE_SIZE;
        let base = PAGE_SIZE / 8; // Number of child pages per page.
        let mut pages = size.div_ceil(rpp);
        if pages <= 1 { return 0; }
        let mut result  = 1;
        while pages > base
        {
            pages /= base;
            result += 1;
        }
        result
    } 
}

Working on gldf-rs, and the according editor, together with the eulumdat-bevy and acadlisp scripting engine.
The full fledged "offline" browser only GLDF Editor, with 3D visualization of photometric lighting,
fully scriptable in Lisp => gldf.icu