No cars were harmed for this talk: Automotive Rust, amateur style - Frank Lyaruu | EuroRust 2025
https://youtu.be/4sYzxv6YijI
https://redd.it/1pzgeu9
@r_rust
https://youtu.be/4sYzxv6YijI
https://redd.it/1pzgeu9
@r_rust
YouTube
No cars were harmed for this talk: Automotive Rust, amateur style - Frank Lyaruu | EuroRust 2025
No cars were harmed for this talk: Automotive Rust, amateur style - Frank Lyaruu at EuroRust 2025
No cars were harmed for this talk: Automotive Rust, amateur style
Software in cars has a bad reputation. People who love cars think it is too intangible and…
No cars were harmed for this talk: Automotive Rust, amateur style
Software in cars has a bad reputation. People who love cars think it is too intangible and…
This media is not supported in your browser
VIEW IN TELEGRAM
[Media] Nexus: Terminal HTTP client with gRPC support and Postman imports!
https://redd.it/1pzizr0
@r_rust
https://redd.it/1pzizr0
@r_rust
ts-bridge – Rust tsserver shim for Neovim
Hey folks, I’ve been working on ts-bridge, a Rust-native shim that sits between Neovim’s LSP client and Microsoft’s tsserver. Neovim already works with typenoscript-language-server, but that project lives entirely in Node/TypeScript, so every buffer sync gets funneled through a JS runtime that pre-spawns tsserver and marshals JSON before the real compiler sees it.
On large TS workspaces that extra layer becomes sluggish—completions lag, diagnostics stutter, and memory usage climbs just to keep the glue alive. ts-bridge replaces that stack with a single Rust binary and the process lazily launches the tsserver you already have while streaming lsp features without Lua/Node overhead.
Written 100% in Rust and if you’re a Neovim user, give it a shot.
Repo: https://github.com/chojs23/ts-bridge
https://redd.it/1pzik32
@r_rust
Hey folks, I’ve been working on ts-bridge, a Rust-native shim that sits between Neovim’s LSP client and Microsoft’s tsserver. Neovim already works with typenoscript-language-server, but that project lives entirely in Node/TypeScript, so every buffer sync gets funneled through a JS runtime that pre-spawns tsserver and marshals JSON before the real compiler sees it.
On large TS workspaces that extra layer becomes sluggish—completions lag, diagnostics stutter, and memory usage climbs just to keep the glue alive. ts-bridge replaces that stack with a single Rust binary and the process lazily launches the tsserver you already have while streaming lsp features without Lua/Node overhead.
Written 100% in Rust and if you’re a Neovim user, give it a shot.
Repo: https://github.com/chojs23/ts-bridge
https://redd.it/1pzik32
@r_rust
GitHub
GitHub - chojs23/ts-bridge: A Rust TypeScript language-server shim that bridges Neovim's LSP client with tsserver.
A Rust TypeScript language-server shim that bridges Neovim's LSP client with tsserver. - chojs23/ts-bridge
that microsoft rust rewrite post got me thinking about my own c to rust attempt
saw that microsoft post about rewriting c/c++ to rust with ai. reminded me i tried this last year
had a personal c project, around 12k lines. packet analyzer i wrote years ago. wanted to learn rust so figured id port it
tried using ai tools to speed it up. normally use verdent cause i can switch between claude and gpt for different tasks, used claude for the tricky ownership stuff and gpt for basic conversions
basic syntax stuff worked fine. loops and match expressions converted ok
pointers were a disaster tho. ai kept suggesting clone() everywhere or just slapping references on things. had to rethink the whole ownership model
i had this memory pool pattern in c that worked great. ai tried converting it literally. complete nonsense in rust. ended up just using vec and letting rust handle it
took way longer than expected. got maybe half done before i gave up and started over with a cleaner design
the "it compiles" thing bit me hard. borrow checker was happy but runtime behavior was wrong. spent days debugging that
microsofts 1 million lines per month claim seems crazy. maybe for trivial code but real systems have so much implicit knowledge baked in
ai is useful for boilerplate but the hard parts you gotta understand yourself
https://redd.it/1pzmsc9
@r_rust
saw that microsoft post about rewriting c/c++ to rust with ai. reminded me i tried this last year
had a personal c project, around 12k lines. packet analyzer i wrote years ago. wanted to learn rust so figured id port it
tried using ai tools to speed it up. normally use verdent cause i can switch between claude and gpt for different tasks, used claude for the tricky ownership stuff and gpt for basic conversions
basic syntax stuff worked fine. loops and match expressions converted ok
pointers were a disaster tho. ai kept suggesting clone() everywhere or just slapping references on things. had to rethink the whole ownership model
i had this memory pool pattern in c that worked great. ai tried converting it literally. complete nonsense in rust. ended up just using vec and letting rust handle it
took way longer than expected. got maybe half done before i gave up and started over with a cleaner design
the "it compiles" thing bit me hard. borrow checker was happy but runtime behavior was wrong. spent days debugging that
microsofts 1 million lines per month claim seems crazy. maybe for trivial code but real systems have so much implicit knowledge baked in
ai is useful for boilerplate but the hard parts you gotta understand yourself
https://redd.it/1pzmsc9
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Investigating and fixing a nasty clone bug
https://kobzol.github.io/rust/2025/12/30/investigating-and-fixing-a-nasty-clone-bug.html
https://redd.it/1pzjj94
@r_rust
https://kobzol.github.io/rust/2025/12/30/investigating-and-fixing-a-nasty-clone-bug.html
https://redd.it/1pzjj94
@r_rust
Kobzol’s blog
Investigating and fixing a nasty clone bug
Recently I found myself battling with another nasty bug. It took me several hours to understand what is happening, and once I found it, it turned out that the cause of the bug is relevant to the Ergonomic cloning initiative that is currently being discussed…
I ported my first open-source project from Swift to Rust and reduced the ram usage by ~80%
Hi all!
I have been working on a project designed to replicate the feeling of using a trackball on macOS- specifically the "momentum pointer" which is a feature present on iPadOS and some Synaptics touchpads. As far as I know, my project is the only known implementation of this on macOS.
I decided to build the first version of this project in Swift. I chose Swift originally because it appeared very syntactically similar to javanoscript (which is what I use primarily in my day job) and seemed to be the easiest to integrate with Apple frameworks.
Eventually I finished it and was satisfied with the result, but felt that there was a lot of bloat (partially due to some LLM use) and that the application was not efficient enough. It hovered around 30MB of ram constantly and would absolutely destroy my macbook's battery life.
I had been interested in learning Rust for a while and after a quick skim of this great article, I began porting the entire codebase. It was a great learning opportunity for me and I was even able to reduce a lot of the complexity that my LLM use in the Swift version caused. I was pleasantly surprised that I was able to find crates for all of the Apple frameworks I needed to make it work, and even bindings for necessary private functions.
The experiment has been a great success so far, as the application now hovers around 6MB of ram (1/5 that of the Swift version) and has a minimal impact to battery life. I only needed an LLM for one part of the codebase, being the trackpad integration since I didn't have a great understanding of some of the deeper concepts necessary for it. I do plan on going back to it though after I've done a little more learning.
Take a look at the project here: https://github.com/margooey/lapsus\_rust/
Article mentioned: https://rust-unofficial.github.io/too-many-lists/
https://redd.it/1pznbfy
@r_rust
Hi all!
I have been working on a project designed to replicate the feeling of using a trackball on macOS- specifically the "momentum pointer" which is a feature present on iPadOS and some Synaptics touchpads. As far as I know, my project is the only known implementation of this on macOS.
I decided to build the first version of this project in Swift. I chose Swift originally because it appeared very syntactically similar to javanoscript (which is what I use primarily in my day job) and seemed to be the easiest to integrate with Apple frameworks.
Eventually I finished it and was satisfied with the result, but felt that there was a lot of bloat (partially due to some LLM use) and that the application was not efficient enough. It hovered around 30MB of ram constantly and would absolutely destroy my macbook's battery life.
I had been interested in learning Rust for a while and after a quick skim of this great article, I began porting the entire codebase. It was a great learning opportunity for me and I was even able to reduce a lot of the complexity that my LLM use in the Swift version caused. I was pleasantly surprised that I was able to find crates for all of the Apple frameworks I needed to make it work, and even bindings for necessary private functions.
The experiment has been a great success so far, as the application now hovers around 6MB of ram (1/5 that of the Swift version) and has a minimal impact to battery life. I only needed an LLM for one part of the codebase, being the trackpad integration since I didn't have a great understanding of some of the deeper concepts necessary for it. I do plan on going back to it though after I've done a little more learning.
Take a look at the project here: https://github.com/margooey/lapsus\_rust/
Article mentioned: https://rust-unofficial.github.io/too-many-lists/
https://redd.it/1pznbfy
@r_rust
GitHub
GitHub - margooey/lapsus_rust: a re-write of Lapsus in rust for speed and power efficiency
a re-write of Lapsus in rust for speed and power efficiency - margooey/lapsus_rust
Optimizing RAM usage of Rust Analyzer
Do you guys have any tips for optimizing RAM usage? In some of my projects, RAM usage can reach 6 GB. What configurations do you use in your IDEs? I'm using Zed Editor at the moment.
https://redd.it/1pzmhxh
@r_rust
Do you guys have any tips for optimizing RAM usage? In some of my projects, RAM usage can reach 6 GB. What configurations do you use in your IDEs? I'm using Zed Editor at the moment.
https://redd.it/1pzmhxh
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Are we official gRPC yet?
At the gRPC Conf in September, there was a presentation on the official support for gRPC in Rust. During the presentation, some milestones were shared which included a beta release in late 2025. Has anyone seen a status update on this or know where this announcement would be communicated?
https://redd.it/1pzkd63
@r_rust
At the gRPC Conf in September, there was a presentation on the official support for gRPC in Rust. During the presentation, some milestones were shared which included a beta release in late 2025. Has anyone seen a status update on this or know where this announcement would be communicated?
https://redd.it/1pzkd63
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Rust project ideas that stress ownership & lifetimes (beginner-friendly)
I’ve been practicing Rust on Codewars and I’m getting more comfortable with ownership and lifetimes — but I want to apply them in real projects.
I have ~10 hours/week and I’m looking for beginner-friendly projects that naturally force you to think about borrowing, references, and structuring data safely (not just another CRUD app).
So far I’ve done small CLIs and websites, but nothing bigger.
What projects helped you really understand the borrow checker — and why?
https://redd.it/1pzuy2q
@r_rust
I’ve been practicing Rust on Codewars and I’m getting more comfortable with ownership and lifetimes — but I want to apply them in real projects.
I have ~10 hours/week and I’m looking for beginner-friendly projects that naturally force you to think about borrowing, references, and structuring data safely (not just another CRUD app).
So far I’ve done small CLIs and websites, but nothing bigger.
What projects helped you really understand the borrow checker — and why?
https://redd.it/1pzuy2q
@r_rust
Reddit
From the rust community on Reddit
Explore this post and more from the rust community
Blowing Up Voxel Asteroids in Rust: SVOs, Physics, and Why Explosions Are Harder Than They Look
I'm working on a voxel space mining game in Rust (wgpu + hecs) and recently finished the explosive system. Thought I'd share how it works since voxel destruction with proper physics is one of those things that sounds simple until you actually try to build it.
GIF
The game has asteroids made of voxels that you can mine or blow apart. When an explosive goes off, it needs to:
1. Carve a spherical hole in the voxel data
2. Spawn debris chunks flying outward
3. Detect if the asteroid split into disconnected pieces
4. Update center of mass and physics for everything
5. Regenerate meshes without hitching
# The Voxel Structure: Sparse Voxel Octree
Asteroids use an SVO instead of a flat 3D array. A 64³ asteroid would need 262k entries in an array, but most of that is empty space. The SVO only stores what's actually there:
pub enum SvoNode {
Leaf(VoxelMaterial),
Branch(Box<Option<SvoNode>; 8>),
}
pub struct Svo {
pub root: Option<SvoNode>,
pub size: u32, // Must be power of 2
pub depth: u32,
}
Each branch divides space into 8 octants. To find which child a coordinate belongs to, you check the relevant bit at each level:
fn childindex(x: u32, y: u32, z: u32, level: u32) -> usize {
let bit = 1 << level;
let ix = ((x & bit) != 0) as usize;
let iy = ((y & bit) != 0) as usize;
let iz = ((z & bit) != 0) as usize;
ix | (iy << 1) | (iz << 2)
}
This gives you O(log n) lookups and inserts, and empty regions don't cost memory.
# Spherical Blast Damage
When a bomb goes off, we need to remove all voxels within the blast radius. The naive approach iterates the bounding box and checks distance:
pub fn applyblastdamage(svo: &mut Svo, center: Vec3, radius: f32) -> u32 {
let mut removed = 0;
let size = svo.size as f32;
let minx = ((center.x - radius).max(0.0)) as u32;
let maxx = ((center.x + radius).min(size - 1.0)) as u32;
// ... same for y, z
for x in minx..=maxx {
for y in miny..=maxy {
for z in minz..=maxz {
let voxelpos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxelpos - center).length() <= radius {
if svo.get(x, y, z) != VoxelMaterial::Empty {
svo.set(x, y, z, VoxelMaterial::Empty);
removed += 1;
}
}
}
}
}
removed
}
With a blast radius of 8 voxels, you're checking at most 16³ = 4096 positions. Not elegant but it runs in microseconds.
# Debris Chunking by Octant
Here's where it gets interesting. The voxels we removed should fly outward as debris. But spawning hundreds of individual voxels would be a mess. Instead, I group them by which octant they're in relative to the blast center:
// Group voxels into chunks based on their octant relative to blast center
let mut chunks: [Vec<(u32, u32, u32, VoxelMaterial)>; 8] = Default::default();
for x in minx..=maxx {
for y in miny..=maxy {
for z in minz..=maxz {
let voxelpos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxelpos - blastcenter).length() <= radius {
let material = svo.get(x, y, z);
if material != VoxelMaterial::Empty {
// Determine octant (0-7) based on position relative to blast center
let octant = ((if voxelpos.x > blastcenter.x { 1 } else { 0 })
| (if voxelpos.y > blastcenter.y { 2 } else { 0 })
| (if voxelpos.z > blastcenter.z { 4 } else { 0 })) as usize;
chunksoctant.push((x, y, z, material));
}
I'm working on a voxel space mining game in Rust (wgpu + hecs) and recently finished the explosive system. Thought I'd share how it works since voxel destruction with proper physics is one of those things that sounds simple until you actually try to build it.
GIF
The game has asteroids made of voxels that you can mine or blow apart. When an explosive goes off, it needs to:
1. Carve a spherical hole in the voxel data
2. Spawn debris chunks flying outward
3. Detect if the asteroid split into disconnected pieces
4. Update center of mass and physics for everything
5. Regenerate meshes without hitching
# The Voxel Structure: Sparse Voxel Octree
Asteroids use an SVO instead of a flat 3D array. A 64³ asteroid would need 262k entries in an array, but most of that is empty space. The SVO only stores what's actually there:
pub enum SvoNode {
Leaf(VoxelMaterial),
Branch(Box<Option<SvoNode>; 8>),
}
pub struct Svo {
pub root: Option<SvoNode>,
pub size: u32, // Must be power of 2
pub depth: u32,
}
Each branch divides space into 8 octants. To find which child a coordinate belongs to, you check the relevant bit at each level:
fn childindex(x: u32, y: u32, z: u32, level: u32) -> usize {
let bit = 1 << level;
let ix = ((x & bit) != 0) as usize;
let iy = ((y & bit) != 0) as usize;
let iz = ((z & bit) != 0) as usize;
ix | (iy << 1) | (iz << 2)
}
This gives you O(log n) lookups and inserts, and empty regions don't cost memory.
# Spherical Blast Damage
When a bomb goes off, we need to remove all voxels within the blast radius. The naive approach iterates the bounding box and checks distance:
pub fn applyblastdamage(svo: &mut Svo, center: Vec3, radius: f32) -> u32 {
let mut removed = 0;
let size = svo.size as f32;
let minx = ((center.x - radius).max(0.0)) as u32;
let maxx = ((center.x + radius).min(size - 1.0)) as u32;
// ... same for y, z
for x in minx..=maxx {
for y in miny..=maxy {
for z in minz..=maxz {
let voxelpos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxelpos - center).length() <= radius {
if svo.get(x, y, z) != VoxelMaterial::Empty {
svo.set(x, y, z, VoxelMaterial::Empty);
removed += 1;
}
}
}
}
}
removed
}
With a blast radius of 8 voxels, you're checking at most 16³ = 4096 positions. Not elegant but it runs in microseconds.
# Debris Chunking by Octant
Here's where it gets interesting. The voxels we removed should fly outward as debris. But spawning hundreds of individual voxels would be a mess. Instead, I group them by which octant they're in relative to the blast center:
// Group voxels into chunks based on their octant relative to blast center
let mut chunks: [Vec<(u32, u32, u32, VoxelMaterial)>; 8] = Default::default();
for x in minx..=maxx {
for y in miny..=maxy {
for z in minz..=maxz {
let voxelpos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxelpos - blastcenter).length() <= radius {
let material = svo.get(x, y, z);
if material != VoxelMaterial::Empty {
// Determine octant (0-7) based on position relative to blast center
let octant = ((if voxelpos.x > blastcenter.x { 1 } else { 0 })
| (if voxelpos.y > blastcenter.y { 2 } else { 0 })
| (if voxelpos.z > blastcenter.z { 4 } else { 0 })) as usize;
chunksoctant.push((x, y, z, material));
}
}
}
}
}
Each octant chunk becomes its own mini-asteroid with its own SVO. This gives you up to 8 debris pieces flying in roughly sensible directions without any fancy clustering algorthm.
# Debris Physics: Inheriting Momentum
The debris velocity calculation is my favorite part. Each chunk needs to inherit the parent asteroid's linear velocity, PLUS the tangential velocity from the asteroid's spin at that point, PLUS an outward explosion impulse:
// Direction: outward from asteroid center
let outwardlocal = chunklocal.normalizeorzero();
let outwardworld = asteroidrotation outward_local;
// World-space offset for tangential velocity calculation
let world_offset = asteroid_rotation chunklocal;
let tangentialvelocity = asteroidangularvelocity.cross(worldoffset);
// Final velocity: parent + spin contribution + explosion
let explosionspeed = DEBRISSPEED * (0.8 + rng.f32() * 0.4);
let velocity = asteroidvelocity + tangentialvelocity + outwardworld explosion_speed;
// Random tumble for visual variety
let angular_velocity = Vec3::new(
rng.f32() 4.0 - 2.0,
rng.f32() 4.0 - 2.0,
rng.f32() 4.0 - 2.0,
);
If the asteroid was spinning when you blew it up, the debris on the leading edge flies faster than the trailing edge. It looks really satisfying when chunks spiral outward.
# Connected Components: Did We Split It?
After the explosion, the parent asteroid might be split into disconnected chunks. We detect this with a basic BFS flood fill:
pub fn findconnectedcomponents(svo: &Svo) -> Vec<HashSet<(u32, u32, u32)>> {
let mut visited = HashSet::new();
let mut components = Vec::new();
for (x, y, z, material) in svo.itervoxels() {
if material == VoxelMaterial::Empty || visited.contains(&(x, y, z)) {
continue;
}
// BFS flood fill from this voxel
let mut component = HashSet::new();
let mut queue = VecDeque::new();
queue.pushback((x, y, z));
while let Some((cx, cy, cz)) = queue.popfront() {
if visited.contains(&(cx, cy, cz)) {
continue;
}
if svo.get(cx, cy, cz) == VoxelMaterial::Empty {
continue;
}
visited.insert((cx, cy, cz));
component.insert((cx, cy, cz));
// Check 6-connected neighbors (face-adjacent only)
let neighbors: [(i32, i32, i32); 6] = [
(1, 0, 0), (-1, 0, 0),
(0, 1, 0), (0, -1, 0),
(0, 0, 1), (0, 0, -1),
];
for (dx, dy, dz) in neighbors {
let nx = cx as i32 + dx;
let ny = cy as i32 + dy;
let nz = cz as i32 + dz;
if nx >= 0 && ny >= 0 && nz >= 0
&& (nx as u32) < svo.size
&& (ny as u32) < svo.size
&& (nz as u32) < svo.size
{
let pos = (nx as u32, ny as u32, nz as u32);
if !visited.contains(&pos) {
queue.pushback(pos);
}
}
}
}
if !component.isempty() {
components.push(component);
}
}
components
}
If we get more than one component, we spawn each as a seperate asteroid. Small fragments (< 50 voxels) just get destroyed since they're not worth tracking.
# Center of Mass Tracking
For physics to feel right, rotation needs to happen around the actual center of mass, not the geometric center. When you mine one voxel at a time, you can update incrementally:
pub fn minevoxel(&mut self, x: u32, y: u32, z: u32) -> VoxelMaterial {
let material = self.svo.remove(x, y, z);
}
}
}
Each octant chunk becomes its own mini-asteroid with its own SVO. This gives you up to 8 debris pieces flying in roughly sensible directions without any fancy clustering algorthm.
# Debris Physics: Inheriting Momentum
The debris velocity calculation is my favorite part. Each chunk needs to inherit the parent asteroid's linear velocity, PLUS the tangential velocity from the asteroid's spin at that point, PLUS an outward explosion impulse:
// Direction: outward from asteroid center
let outwardlocal = chunklocal.normalizeorzero();
let outwardworld = asteroidrotation outward_local;
// World-space offset for tangential velocity calculation
let world_offset = asteroid_rotation chunklocal;
let tangentialvelocity = asteroidangularvelocity.cross(worldoffset);
// Final velocity: parent + spin contribution + explosion
let explosionspeed = DEBRISSPEED * (0.8 + rng.f32() * 0.4);
let velocity = asteroidvelocity + tangentialvelocity + outwardworld explosion_speed;
// Random tumble for visual variety
let angular_velocity = Vec3::new(
rng.f32() 4.0 - 2.0,
rng.f32() 4.0 - 2.0,
rng.f32() 4.0 - 2.0,
);
If the asteroid was spinning when you blew it up, the debris on the leading edge flies faster than the trailing edge. It looks really satisfying when chunks spiral outward.
# Connected Components: Did We Split It?
After the explosion, the parent asteroid might be split into disconnected chunks. We detect this with a basic BFS flood fill:
pub fn findconnectedcomponents(svo: &Svo) -> Vec<HashSet<(u32, u32, u32)>> {
let mut visited = HashSet::new();
let mut components = Vec::new();
for (x, y, z, material) in svo.itervoxels() {
if material == VoxelMaterial::Empty || visited.contains(&(x, y, z)) {
continue;
}
// BFS flood fill from this voxel
let mut component = HashSet::new();
let mut queue = VecDeque::new();
queue.pushback((x, y, z));
while let Some((cx, cy, cz)) = queue.popfront() {
if visited.contains(&(cx, cy, cz)) {
continue;
}
if svo.get(cx, cy, cz) == VoxelMaterial::Empty {
continue;
}
visited.insert((cx, cy, cz));
component.insert((cx, cy, cz));
// Check 6-connected neighbors (face-adjacent only)
let neighbors: [(i32, i32, i32); 6] = [
(1, 0, 0), (-1, 0, 0),
(0, 1, 0), (0, -1, 0),
(0, 0, 1), (0, 0, -1),
];
for (dx, dy, dz) in neighbors {
let nx = cx as i32 + dx;
let ny = cy as i32 + dy;
let nz = cz as i32 + dz;
if nx >= 0 && ny >= 0 && nz >= 0
&& (nx as u32) < svo.size
&& (ny as u32) < svo.size
&& (nz as u32) < svo.size
{
let pos = (nx as u32, ny as u32, nz as u32);
if !visited.contains(&pos) {
queue.pushback(pos);
}
}
}
}
if !component.isempty() {
components.push(component);
}
}
components
}
If we get more than one component, we spawn each as a seperate asteroid. Small fragments (< 50 voxels) just get destroyed since they're not worth tracking.
# Center of Mass Tracking
For physics to feel right, rotation needs to happen around the actual center of mass, not the geometric center. When you mine one voxel at a time, you can update incrementally:
pub fn minevoxel(&mut self, x: u32, y: u32, z: u32) -> VoxelMaterial {
let material = self.svo.remove(x, y, z);
Blowing Up Voxel Asteroids in Rust: SVOs, Physics, and Why Explosions Are Harder Than They Look
I'm working on a voxel space mining game in Rust (wgpu + hecs) and recently finished the explosive system. Thought I'd share how it works since voxel destruction with proper physics is one of those things that sounds simple until you actually try to build it.
[GIF ](https://imgur.com/a/h5Gl5So)
The game has asteroids made of voxels that you can mine or blow apart. When an explosive goes off, it needs to:
1. Carve a spherical hole in the voxel data
2. Spawn debris chunks flying outward
3. Detect if the asteroid split into disconnected pieces
4. Update center of mass and physics for everything
5. Regenerate meshes without hitching
# The Voxel Structure: Sparse Voxel Octree
Asteroids use an SVO instead of a flat 3D array. A 64³ asteroid would need 262k entries in an array, but most of that is empty space. The SVO only stores what's actually there:
pub enum SvoNode {
Leaf(VoxelMaterial),
Branch(Box<[Option<SvoNode>; 8]>),
}
pub struct Svo {
pub root: Option<SvoNode>,
pub size: u32, // Must be power of 2
pub depth: u32,
}
Each branch divides space into 8 octants. To find which child a coordinate belongs to, you check the relevant bit at each level:
fn child_index(x: u32, y: u32, z: u32, level: u32) -> usize {
let bit = 1 << level;
let ix = ((x & bit) != 0) as usize;
let iy = ((y & bit) != 0) as usize;
let iz = ((z & bit) != 0) as usize;
ix | (iy << 1) | (iz << 2)
}
This gives you O(log n) lookups and inserts, and empty regions don't cost memory.
# Spherical Blast Damage
When a bomb goes off, we need to remove all voxels within the blast radius. The naive approach iterates the bounding box and checks distance:
pub fn apply_blast_damage(svo: &mut Svo, center: Vec3, radius: f32) -> u32 {
let mut removed = 0;
let size = svo.size as f32;
let min_x = ((center.x - radius).max(0.0)) as u32;
let max_x = ((center.x + radius).min(size - 1.0)) as u32;
// ... same for y, z
for x in min_x..=max_x {
for y in min_y..=max_y {
for z in min_z..=max_z {
let voxel_pos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxel_pos - center).length() <= radius {
if svo.get(x, y, z) != VoxelMaterial::Empty {
svo.set(x, y, z, VoxelMaterial::Empty);
removed += 1;
}
}
}
}
}
removed
}
With a blast radius of 8 voxels, you're checking at most 16³ = 4096 positions. Not elegant but it runs in microseconds.
# Debris Chunking by Octant
Here's where it gets interesting. The voxels we removed should fly outward as debris. But spawning hundreds of individual voxels would be a mess. Instead, I group them by which octant they're in relative to the blast center:
// Group voxels into chunks based on their octant relative to blast center
let mut chunks: [Vec<(u32, u32, u32, VoxelMaterial)>; 8] = Default::default();
for x in min_x..=max_x {
for y in min_y..=max_y {
for z in min_z..=max_z {
let voxel_pos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxel_pos - blast_center).length() <= radius {
let material = svo.get(x, y, z);
if material != VoxelMaterial::Empty {
// Determine octant (0-7) based on position relative to blast center
let octant = ((if voxel_pos.x > blast_center.x { 1 } else { 0 })
| (if voxel_pos.y > blast_center.y { 2 } else { 0 })
| (if voxel_pos.z > blast_center.z { 4 } else { 0 })) as usize;
chunks[octant].push((x, y, z, material));
}
I'm working on a voxel space mining game in Rust (wgpu + hecs) and recently finished the explosive system. Thought I'd share how it works since voxel destruction with proper physics is one of those things that sounds simple until you actually try to build it.
[GIF ](https://imgur.com/a/h5Gl5So)
The game has asteroids made of voxels that you can mine or blow apart. When an explosive goes off, it needs to:
1. Carve a spherical hole in the voxel data
2. Spawn debris chunks flying outward
3. Detect if the asteroid split into disconnected pieces
4. Update center of mass and physics for everything
5. Regenerate meshes without hitching
# The Voxel Structure: Sparse Voxel Octree
Asteroids use an SVO instead of a flat 3D array. A 64³ asteroid would need 262k entries in an array, but most of that is empty space. The SVO only stores what's actually there:
pub enum SvoNode {
Leaf(VoxelMaterial),
Branch(Box<[Option<SvoNode>; 8]>),
}
pub struct Svo {
pub root: Option<SvoNode>,
pub size: u32, // Must be power of 2
pub depth: u32,
}
Each branch divides space into 8 octants. To find which child a coordinate belongs to, you check the relevant bit at each level:
fn child_index(x: u32, y: u32, z: u32, level: u32) -> usize {
let bit = 1 << level;
let ix = ((x & bit) != 0) as usize;
let iy = ((y & bit) != 0) as usize;
let iz = ((z & bit) != 0) as usize;
ix | (iy << 1) | (iz << 2)
}
This gives you O(log n) lookups and inserts, and empty regions don't cost memory.
# Spherical Blast Damage
When a bomb goes off, we need to remove all voxels within the blast radius. The naive approach iterates the bounding box and checks distance:
pub fn apply_blast_damage(svo: &mut Svo, center: Vec3, radius: f32) -> u32 {
let mut removed = 0;
let size = svo.size as f32;
let min_x = ((center.x - radius).max(0.0)) as u32;
let max_x = ((center.x + radius).min(size - 1.0)) as u32;
// ... same for y, z
for x in min_x..=max_x {
for y in min_y..=max_y {
for z in min_z..=max_z {
let voxel_pos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxel_pos - center).length() <= radius {
if svo.get(x, y, z) != VoxelMaterial::Empty {
svo.set(x, y, z, VoxelMaterial::Empty);
removed += 1;
}
}
}
}
}
removed
}
With a blast radius of 8 voxels, you're checking at most 16³ = 4096 positions. Not elegant but it runs in microseconds.
# Debris Chunking by Octant
Here's where it gets interesting. The voxels we removed should fly outward as debris. But spawning hundreds of individual voxels would be a mess. Instead, I group them by which octant they're in relative to the blast center:
// Group voxels into chunks based on their octant relative to blast center
let mut chunks: [Vec<(u32, u32, u32, VoxelMaterial)>; 8] = Default::default();
for x in min_x..=max_x {
for y in min_y..=max_y {
for z in min_z..=max_z {
let voxel_pos = Vec3::new(x as f32 + 0.5, y as f32 + 0.5, z as f32 + 0.5);
if (voxel_pos - blast_center).length() <= radius {
let material = svo.get(x, y, z);
if material != VoxelMaterial::Empty {
// Determine octant (0-7) based on position relative to blast center
let octant = ((if voxel_pos.x > blast_center.x { 1 } else { 0 })
| (if voxel_pos.y > blast_center.y { 2 } else { 0 })
| (if voxel_pos.z > blast_center.z { 4 } else { 0 })) as usize;
chunks[octant].push((x, y, z, material));
}
}
}
}
}
Each octant chunk becomes its own mini-asteroid with its own SVO. This gives you up to 8 debris pieces flying in roughly sensible directions without any fancy clustering algorthm.
# Debris Physics: Inheriting Momentum
The debris velocity calculation is my favorite part. Each chunk needs to inherit the parent asteroid's linear velocity, PLUS the tangential velocity from the asteroid's spin at that point, PLUS an outward explosion impulse:
// Direction: outward from asteroid center
let outward_local = chunk_local.normalize_or_zero();
let outward_world = asteroid_rotation * outward_local;
// World-space offset for tangential velocity calculation
let world_offset = asteroid_rotation * chunk_local;
let tangential_velocity = asteroid_angular_velocity.cross(world_offset);
// Final velocity: parent + spin contribution + explosion
let explosion_speed = DEBRIS_SPEED * (0.8 + rng.f32() * 0.4);
let velocity = asteroid_velocity + tangential_velocity + outward_world * explosion_speed;
// Random tumble for visual variety
let angular_velocity = Vec3::new(
rng.f32() * 4.0 - 2.0,
rng.f32() * 4.0 - 2.0,
rng.f32() * 4.0 - 2.0,
);
If the asteroid was spinning when you blew it up, the debris on the leading edge flies faster than the trailing edge. It looks really satisfying when chunks spiral outward.
# Connected Components: Did We Split It?
After the explosion, the parent asteroid might be split into disconnected chunks. We detect this with a basic BFS flood fill:
pub fn find_connected_components(svo: &Svo) -> Vec<HashSet<(u32, u32, u32)>> {
let mut visited = HashSet::new();
let mut components = Vec::new();
for (x, y, z, material) in svo.iter_voxels() {
if material == VoxelMaterial::Empty || visited.contains(&(x, y, z)) {
continue;
}
// BFS flood fill from this voxel
let mut component = HashSet::new();
let mut queue = VecDeque::new();
queue.push_back((x, y, z));
while let Some((cx, cy, cz)) = queue.pop_front() {
if visited.contains(&(cx, cy, cz)) {
continue;
}
if svo.get(cx, cy, cz) == VoxelMaterial::Empty {
continue;
}
visited.insert((cx, cy, cz));
component.insert((cx, cy, cz));
// Check 6-connected neighbors (face-adjacent only)
let neighbors: [(i32, i32, i32); 6] = [
(1, 0, 0), (-1, 0, 0),
(0, 1, 0), (0, -1, 0),
(0, 0, 1), (0, 0, -1),
];
for (dx, dy, dz) in neighbors {
let nx = cx as i32 + dx;
let ny = cy as i32 + dy;
let nz = cz as i32 + dz;
if nx >= 0 && ny >= 0 && nz >= 0
&& (nx as u32) < svo.size
&& (ny as u32) < svo.size
&& (nz as u32) < svo.size
{
let pos = (nx as u32, ny as u32, nz as u32);
if !visited.contains(&pos) {
queue.push_back(pos);
}
}
}
}
if !component.is_empty() {
components.push(component);
}
}
components
}
If we get more than one component, we spawn each as a seperate asteroid. Small fragments (< 50 voxels) just get destroyed since they're not worth tracking.
# Center of Mass Tracking
For physics to feel right, rotation needs to happen around the actual center of mass, not the geometric center. When you mine one voxel at a time, you can update incrementally:
pub fn mine_voxel(&mut self, x: u32, y: u32, z: u32) -> VoxelMaterial {
let material = self.svo.remove(x, y, z);
}
}
}
Each octant chunk becomes its own mini-asteroid with its own SVO. This gives you up to 8 debris pieces flying in roughly sensible directions without any fancy clustering algorthm.
# Debris Physics: Inheriting Momentum
The debris velocity calculation is my favorite part. Each chunk needs to inherit the parent asteroid's linear velocity, PLUS the tangential velocity from the asteroid's spin at that point, PLUS an outward explosion impulse:
// Direction: outward from asteroid center
let outward_local = chunk_local.normalize_or_zero();
let outward_world = asteroid_rotation * outward_local;
// World-space offset for tangential velocity calculation
let world_offset = asteroid_rotation * chunk_local;
let tangential_velocity = asteroid_angular_velocity.cross(world_offset);
// Final velocity: parent + spin contribution + explosion
let explosion_speed = DEBRIS_SPEED * (0.8 + rng.f32() * 0.4);
let velocity = asteroid_velocity + tangential_velocity + outward_world * explosion_speed;
// Random tumble for visual variety
let angular_velocity = Vec3::new(
rng.f32() * 4.0 - 2.0,
rng.f32() * 4.0 - 2.0,
rng.f32() * 4.0 - 2.0,
);
If the asteroid was spinning when you blew it up, the debris on the leading edge flies faster than the trailing edge. It looks really satisfying when chunks spiral outward.
# Connected Components: Did We Split It?
After the explosion, the parent asteroid might be split into disconnected chunks. We detect this with a basic BFS flood fill:
pub fn find_connected_components(svo: &Svo) -> Vec<HashSet<(u32, u32, u32)>> {
let mut visited = HashSet::new();
let mut components = Vec::new();
for (x, y, z, material) in svo.iter_voxels() {
if material == VoxelMaterial::Empty || visited.contains(&(x, y, z)) {
continue;
}
// BFS flood fill from this voxel
let mut component = HashSet::new();
let mut queue = VecDeque::new();
queue.push_back((x, y, z));
while let Some((cx, cy, cz)) = queue.pop_front() {
if visited.contains(&(cx, cy, cz)) {
continue;
}
if svo.get(cx, cy, cz) == VoxelMaterial::Empty {
continue;
}
visited.insert((cx, cy, cz));
component.insert((cx, cy, cz));
// Check 6-connected neighbors (face-adjacent only)
let neighbors: [(i32, i32, i32); 6] = [
(1, 0, 0), (-1, 0, 0),
(0, 1, 0), (0, -1, 0),
(0, 0, 1), (0, 0, -1),
];
for (dx, dy, dz) in neighbors {
let nx = cx as i32 + dx;
let ny = cy as i32 + dy;
let nz = cz as i32 + dz;
if nx >= 0 && ny >= 0 && nz >= 0
&& (nx as u32) < svo.size
&& (ny as u32) < svo.size
&& (nz as u32) < svo.size
{
let pos = (nx as u32, ny as u32, nz as u32);
if !visited.contains(&pos) {
queue.push_back(pos);
}
}
}
}
if !component.is_empty() {
components.push(component);
}
}
components
}
If we get more than one component, we spawn each as a seperate asteroid. Small fragments (< 50 voxels) just get destroyed since they're not worth tracking.
# Center of Mass Tracking
For physics to feel right, rotation needs to happen around the actual center of mass, not the geometric center. When you mine one voxel at a time, you can update incrementally:
pub fn mine_voxel(&mut self, x: u32, y: u32, z: u32) -> VoxelMaterial {
let material = self.svo.remove(x, y, z);
if material.is_solid() && self.voxel_count > 1 {
let center = self.svo.size as f32 / 2.0;
let removed_pos = Vec3::new(
x as f32 - center,
y as f32 - center,
z as f32 - center
);
// Incremental CoM update: new = (old * old_count - removed) / new_count
let old_count = self.voxel_count as f32;
let new_count = (self.voxel_count - 1) as f32;
self.center_of_mass = (self.center_of_mass * old_count - removed_pos) / new_count;
self.voxel_count -= 1;
}
material
}
For explosions where you remove hundreds of voxels at once, incremental updates would accumulate floating point error. So I just recalculate from scratch:
let mut com_sum = Vec3::ZERO;
let mut count = 0u32;
for (x, y, z, mat) in asteroid.svo.iter_voxels() {
if mat != VoxelMaterial::Empty {
com_sum += Vec3::new(
x as f32 - svo_center,
y as f32 - svo_center,
z as f32 - svo_center,
);
count += 1;
}
}
asteroid.center_of_mass = com_sum / count as f32;
# Mesh Generation: Only Exposed Faces
You don't want to render faces between adjacent solid voxels. For each voxel, check its 6 neighbors and only emit faces where the neighbor is empty:
for (x, y, z, material) in self.svo.iter_voxels() {
let neighbors = [
(1i32, 0i32, 0i32, [1.0, 0.0, 0.0]), // +X
(-1, 0, 0, [-1.0, 0.0, 0.0]), // -X
(0, 1, 0, [0.0, 1.0, 0.0]), // +Y
(0, -1, 0, [0.0, -1.0, 0.0]), // -Y
(0, 0, 1, [0.0, 0.0, 1.0]), // +Z
(0, 0, -1, [0.0, 0.0, -1.0]), // -Z
];
for (i, (dx, dy, dz, normal)) in neighbors.iter().enumerate() {
let nx = x as i32 + dx;
let ny = y as i32 + dy;
let nz = z as i32 + dz;
let neighbor_solid = /* bounds check && svo.is_solid(...) */;
if !neighbor_solid {
// Emit this face's 4 vertices and 2 triangles
}
}
}
I also compute per-vertex ambient occlusion by checking the 3 neighbors at each corner. It makes a huge visual difference for basically no runtime cost.
# Putting It Together
The full detonation flow:
1. Find all attached explosives
2. For each: extract debris chunks, remove voxels from parent
3. Run connected components on the damaged parent
4. Recalculate CoM and mass for parent
5. Queue mesh regeneration (happens on background thread)
6. Spawn debris entities with inherited physics
7. Add 3 second collision cooldown so debris doesn't immediately bounce back
The collision cooldown is a bit of a hack but it prevents physics instability when chunks spawn overlapping their parent.
# What I'd Do Differently
The octant-based debris grouping works but sometimes produces weird shapes. A proper k-means clustering or marching cubes approach would give nicer chunks. Also my connected components check iterates all voxels which is O(n), could probably use the SVO structure to skip empty regions.
But honestly? It works, it's fast enough, and explosions feel good. Sometimes good enough is good enough.
You can follow/wishlist Asteroid Rodeo[ here.](https://asteroidrodeo.leadbooster.co)
https://redd.it/1pzwavt
@r_rust
let center = self.svo.size as f32 / 2.0;
let removed_pos = Vec3::new(
x as f32 - center,
y as f32 - center,
z as f32 - center
);
// Incremental CoM update: new = (old * old_count - removed) / new_count
let old_count = self.voxel_count as f32;
let new_count = (self.voxel_count - 1) as f32;
self.center_of_mass = (self.center_of_mass * old_count - removed_pos) / new_count;
self.voxel_count -= 1;
}
material
}
For explosions where you remove hundreds of voxels at once, incremental updates would accumulate floating point error. So I just recalculate from scratch:
let mut com_sum = Vec3::ZERO;
let mut count = 0u32;
for (x, y, z, mat) in asteroid.svo.iter_voxels() {
if mat != VoxelMaterial::Empty {
com_sum += Vec3::new(
x as f32 - svo_center,
y as f32 - svo_center,
z as f32 - svo_center,
);
count += 1;
}
}
asteroid.center_of_mass = com_sum / count as f32;
# Mesh Generation: Only Exposed Faces
You don't want to render faces between adjacent solid voxels. For each voxel, check its 6 neighbors and only emit faces where the neighbor is empty:
for (x, y, z, material) in self.svo.iter_voxels() {
let neighbors = [
(1i32, 0i32, 0i32, [1.0, 0.0, 0.0]), // +X
(-1, 0, 0, [-1.0, 0.0, 0.0]), // -X
(0, 1, 0, [0.0, 1.0, 0.0]), // +Y
(0, -1, 0, [0.0, -1.0, 0.0]), // -Y
(0, 0, 1, [0.0, 0.0, 1.0]), // +Z
(0, 0, -1, [0.0, 0.0, -1.0]), // -Z
];
for (i, (dx, dy, dz, normal)) in neighbors.iter().enumerate() {
let nx = x as i32 + dx;
let ny = y as i32 + dy;
let nz = z as i32 + dz;
let neighbor_solid = /* bounds check && svo.is_solid(...) */;
if !neighbor_solid {
// Emit this face's 4 vertices and 2 triangles
}
}
}
I also compute per-vertex ambient occlusion by checking the 3 neighbors at each corner. It makes a huge visual difference for basically no runtime cost.
# Putting It Together
The full detonation flow:
1. Find all attached explosives
2. For each: extract debris chunks, remove voxels from parent
3. Run connected components on the damaged parent
4. Recalculate CoM and mass for parent
5. Queue mesh regeneration (happens on background thread)
6. Spawn debris entities with inherited physics
7. Add 3 second collision cooldown so debris doesn't immediately bounce back
The collision cooldown is a bit of a hack but it prevents physics instability when chunks spawn overlapping their parent.
# What I'd Do Differently
The octant-based debris grouping works but sometimes produces weird shapes. A proper k-means clustering or marching cubes approach would give nicer chunks. Also my connected components check iterates all voxels which is O(n), could probably use the SVO structure to skip empty regions.
But honestly? It works, it's fast enough, and explosions feel good. Sometimes good enough is good enough.
You can follow/wishlist Asteroid Rodeo[ here.](https://asteroidrodeo.leadbooster.co)
https://redd.it/1pzwavt
@r_rust
Steampowered
Asteroid Rodeo on Steam
Tame spinning asteroids with harpoons and thrusters. Mine them for profit. Upgrade your ship. A physics sandbox where every rock fights back.
Polynomial Regression crate (loess-rs) now available
Hey everyone. Just wanted to announce that a fully featured, robust, and solid Polynomial Regression (LOESS) crate has been released for Rust, available at loess-rs.
It is 3-25x faster than the original Fortran implementation by Cleveland (available in base R and Python scikit-misc package), and is as accurate (and even more robust) than the original implementation + offers a TON of new features on top of it: confidence/prediction intervals, cross-validation, boundary padding, different robustness weights, different kernels, ...
This is genuinely the most robust, the most flexible, and the fastest implementation of this frequently used algorithm in data science.
I believe Rust offers a perfect environment for implementing data science/bioinformatics algorithms, and I hope my crate contributes to the growing interest and usage by the community 🙌
https://redd.it/1q068hj
@r_rust
Hey everyone. Just wanted to announce that a fully featured, robust, and solid Polynomial Regression (LOESS) crate has been released for Rust, available at loess-rs.
It is 3-25x faster than the original Fortran implementation by Cleveland (available in base R and Python scikit-misc package), and is as accurate (and even more robust) than the original implementation + offers a TON of new features on top of it: confidence/prediction intervals, cross-validation, boundary padding, different robustness weights, different kernels, ...
This is genuinely the most robust, the most flexible, and the fastest implementation of this frequently used algorithm in data science.
I believe Rust offers a perfect environment for implementing data science/bioinformatics algorithms, and I hope my crate contributes to the growing interest and usage by the community 🙌
https://redd.it/1q068hj
@r_rust
crates.io
crates.io: Rust Package Registry
KHOJ : Rust based Local Search Engine
I have written a rust based local search engine Khoj
the numbers seem to be decent :
=== Indexing Benchmark ===
Indexed 859 files in 3.54s
Indexing Throughput: 242.98 files/sec
Effectively: 23.1 MB/sec
=== Search Benchmark ===
Average Search Latency: 1.68ms
=== Search Throughput Benchmark (5s) ===
Total Queries: 2600
Throughput: 518.58 QPS
What else should i change before publishing this as a package to apt/dnf?
And is it worth adding to resume?
https://redd.it/1q08drx
@r_rust
I have written a rust based local search engine Khoj
the numbers seem to be decent :
=== Indexing Benchmark ===
Indexed 859 files in 3.54s
Indexing Throughput: 242.98 files/sec
Effectively: 23.1 MB/sec
=== Search Benchmark ===
Average Search Latency: 1.68ms
=== Search Throughput Benchmark (5s) ===
Total Queries: 2600
Throughput: 518.58 QPS
What else should i change before publishing this as a package to apt/dnf?
And is it worth adding to resume?
https://redd.it/1q08drx
@r_rust
GitHub
GitHub - shankeleven/khoj: local search engine
local search engine . Contribute to shankeleven/khoj development by creating an account on GitHub.
size_lru : The fastest size-aware LRU cache in Rust
https://crates.io/crates/size_lru#zh
https://redd.it/1q02tls
@r_rust
https://crates.io/crates/size_lru#zh
https://redd.it/1q02tls
@r_rust
crates.io
crates.io: Rust Package Registry
Announcement: aselect! - an alternative to tokio::select
https://github.com/avl/aselect
The tokio
1. When one arm completes, all the other arms are canceled
2. When used in loops, if a handler runs async code, other arms are starved
aselect avoids these pitfalls by never canceling futures, and never starving them. The crate has not seen production use, so there could be bugs.
Feedback and suggestions welcome! Will something like this make async rust less error prone?
https://redd.it/1q0aig1
@r_rust
https://github.com/avl/aselect
The tokio
select! macro has two characteristics that can make it error-prone:1. When one arm completes, all the other arms are canceled
2. When used in loops, if a handler runs async code, other arms are starved
aselect avoids these pitfalls by never canceling futures, and never starving them. The crate has not seen production use, so there could be bugs.
Feedback and suggestions welcome! Will something like this make async rust less error prone?
https://redd.it/1q0aig1
@r_rust
GitHub
GitHub - avl/aselect: Less error-prone (in some ways) alternative to tokio::select
Less error-prone (in some ways) alternative to tokio::select - avl/aselect
Launched Apache DataSketches Rust
https://github.com/apache/datasketches-rust
https://redd.it/1q051s0
@r_rust
https://github.com/apache/datasketches-rust
https://redd.it/1q051s0
@r_rust
GitHub
GitHub - apache/datasketches-rust: A software library of stochastic streaming algorithms, a.k.a. sketches.
A software library of stochastic streaming algorithms, a.k.a. sketches. - apache/datasketches-rust
Create a Rust tool bfinder to find the top largest files.
I Built this rust tool which uses multi-threading to find the largest files fast. https://github.com/aja544/bfinder
Statistics:
Files scanned: 524013
Directories scanned: 124216
Errors: 0
Time elapsed: 4.380s
https://redd.it/1q0b1rz
@r_rust
I Built this rust tool which uses multi-threading to find the largest files fast. https://github.com/aja544/bfinder
Statistics:
Files scanned: 524013
Directories scanned: 124216
Errors: 0
Time elapsed: 4.380s
https://redd.it/1q0b1rz
@r_rust
GitHub
GitHub - aja544/bfinder: A rust based tool to finde the largest files
A rust based tool to finde the largest files. Contribute to aja544/bfinder development by creating an account on GitHub.