febug 1.0.1

anyway, here's user-space debugfs
Documentation
// SPDX-License-Identifier: MIT


extern crate febug;

use std::sync::atomic::{AtomicUsize, Ordering};
use febug::{StaticWrappable, Wrapper};
use std::time::Duration;
use std::any::TypeId;
use std::io::Write;
use std::fs::File;
use std::thread;


static COMPARISONS: AtomicUsize = AtomicUsize::new(0);


fn main() {
    febug::start();
    if febug::install_handler() {
        // Normal registration by TypeId, variables use .wrap(...)
        let mut fmt = febug::FORMATTERS.lock().unwrap();
        fmt.insert(TypeId::of::<String>().into(), |of, vid| {
            let data = unsafe { &*(vid as *const String) };

            let _ = of.write_all(data.as_bytes());
            let _ = of.write_all(b"\n");
        });

        // Custom registration with an explicit type number and Wrapper::new()
        fmt.insert(0.into(), |of: &mut File, _| {
            let _ = write!(of, "{}\n", COMPARISONS.load(Ordering::Relaxed));
        });
    }

    let _comparisons_wrapper = Wrapper::new(0, &COMPARISONS, format_args!("comparisons"));


    let threads = (0..10)
        .map(|i| {
            thread::spawn(move || {
                let mut sorteing = "The quick red fox jumps over the lazy brown \
                                    dog... tHE QUICK RED FOX JUMPS OVER THE \
                                    LAZY BROWN DOG!!"
                                       [0..(i + 1) * 10]
                    .to_string();
                let _sorteing_w = sorteing.wrap(format_args!("cool_data_{}", i));

                unsafe { sorteing.as_bytes_mut() }.sort_unstable_by(|a, b| {
                    thread::sleep(Duration::from_millis(250));
                    COMPARISONS.fetch_add(1, Ordering::Relaxed);
                    a.cmp(b)
                });

                thread::sleep(Duration::from_secs(2));
            })
        })
        .collect::<Vec<_>>();
    for t in threads {
        let _ = t.join();
    }
}