Rust programing language®
448 subscribers
14 photos
188 links
rust programing channel
Download Telegram
I built a portable serial terminal for ESP32/Arduino in Rust — because my board kept resetting

If you debug ESP32 boards over serial, you probably know this one: you flash the firmware, rush to open a serial monitor to catch the boot logs… and the act of opening the monitor resets the board. The DTR/RTS lines toggle on connect, the ESP32 auto-resets, and the first lines you actually wanted are gone.

I hit this enough times that I built my own terminal.

CNTerminal
Live + download: https://www.coding-now.com/en/cnterminal Source (MIT): https://github.com/cflab2017/tool_serial_terminal_Rust

It's a free, portable serial terminal for Windows — a single ~8 MB .exe. No installer, no runtime, no admin rights: drop it on a USB stick, run it on a locked-down lab PC, done.

What it does:

DTR / RTS control — the reason it exists. Keep DTR from toggling on connect and the ESP32 doesn't auto-reset, so you actually see the boot output.
HEX send & receive — for binary protocols, plus an ASCII HEX converter built in (no more alt-tabbing to a converter site mid-debug).
5,000-line auto-trim — long logging sessions don't slowly eat your RAM or lag the UI.
The usual: port/baud selection, timestamps, a dark amber CRT theme that's easy on the eyes during long sessions.
Why Rust + egui
I wanted a single file people could run anywhere, which ruled out anything with a runtime. Rust + egui turned out to be a great fit: the whole GUI app compiles to one small native binary, immediate-mode UI keeps the serial read loop and the rendering loop simple to reason about, and serialport-rs handles the device side.

The trickiest part wasn't the UI — it was making the serial reader thread, the auto-trimmed scrollback buffer, and the GUI repaint cooperate without dropping bytes at high baud rates. If you're curious, the source is MIT and pretty small.

Honest scope
Windows only for now (single-exe portability was the goal).
It's a terminal, not an IDE plugin — it does serial I/O well and nothing else.
If you live in a serial monitor — Arduino, ESP32, STM32, industrial gear over RS-232 — give it a try and tell me what's missing compared to your current setup. Feature requests and bug reports are very welcome, here or on GitHub.

via DEV Community: rust (author: 코딩나우(하늘아래))
Why I still teach Singleton even though modules make it redundant

Ask any developer what design pattern they know best and Singleton comes up first. Ask the same group if they use it in production and half will say no. The module system already does the job.

They're right. But I still include it in my patterns reference, and here's why.

What Singleton actually solves

The pattern ensures a class has only one instance and provides a global access point to it. Shared configuration loaded from env vars, a logger that buffers output, a connection pool you don't want duplicated. That kind of thing.

The classical JavaScript version looks like this:

class Config {
static #instance = null;
#data;

constructor() {
this.#data = {
apiUrl: process.env.API_URL ?? "http://localhost:3000",
timeout: Number(process.env.TIMEOUT ?? 5000),
};
}

static getInstance() {
if (!Config.#instance) {
Config.#instance = new Config();
}
return Config.#instance;
}

get(key) {
return this.#data[key];
}
}


Boilerplate. Every time.

The module alternative
In JavaScript and Python, a module is already a singleton. The runtime caches it after the first import. So the same Config above becomes:

// config.js
export const config = {
apiUrl: process.env.API_URL ?? "http://localhost:3000",
timeout: Number(process.env.TIMEOUT ?? 5000),
};

// anywhere else
import { config } from "./config.js";

Same object, every import, no class, no getInstance(). Python works identically.

So the pattern is "redundant" in the sense that you'd rarely write the classical version in a modern JS or Python codebase. You'd just export a module-level object.

Why I still teach it

Three reasons.

You will read it in older code. Codebases written before ES modules were standard, Python 2-era code, Java and PHP services. If you've never seen the pattern explained properly, you'll waste time figuring out what the class is doing.

It makes the intent explicit. A plain exported object and a Singleton both enforce one instance, but the Singleton makes that constraint visible and enforced at the type level. In teams, explicit beats implicit.

Rust does not have the shortcut. OnceLock (stable since 1.70) or LazyLock (stable since 1.80) is the idiomatic way to get a static singleton in Rust. There is no module-level trick.

use std::sync::LazyLock;

static CONFIG: LazyLock<Config> = LazyLock::new(Config::from_env);

That is the pattern, just dressed in modern syntax.

The broader point

This is what I tried to do with the whole reference. For each of the 23 GoF patterns, show the classical approach and then show what modern language features replaced or simplified it. Some patterns are still essential. Some you'd only write in a language without the shortcut. Some you'll only encounter as a reader, not a writer.

The reference covers all 23 patterns plus the 5 SOLID principles, with examples in JavaScript, Python, and Rust. MIT licensed.

https://github.com/dsheiko/design-patterns-for-web-developer

via DEV Community: rust (author: Dmitry Sheiko)
Tauri v2 Cheatsheet — The Commands I Use on Every Project

All tests run on an 8-year-old MacBook Air. All results from shipping 7 Mac apps as a solo developer. No sponsored opinion.

After 7 Tauri apps, I type the same commands constantly. Here's the reference I wish existed when I started.

Project setup
# New project
npm create tauri-app@latest

# Add to existing project
npm install --save-dev @tauri-apps/cli
npx tauri init


Development
# Dev mode (hot reload)
npm run tauri dev

# Dev with specific log level
RUST_LOG=debug npm run tauri dev

# Dev with backend logs visible
npm run tauri dev 2>&1 | grep -v "^$"


Building
# Standard build
npm run tauri build

# Universal binary (Intel + Apple Silicon)
npm run tauri build -- --target universal-apple-darwin

# Debug build (faster, no optimization)
npm run tauri build -- --debug


Plugins
npm run tauri add global-shortcut
npm run tauri add fs
npm run tauri add shell
npm run tauri add notification

This updates both Cargo.toml and the plugin registration. Faster than doing it manually.

Permissions (tauri.conf.json)
{
"app": {
"security": {
"capabilities": [
{
"identifier": "main-capability",
"description": "Main window capabilities",
"windows": ["main"],
"permissions": [
"fs:read-all",
"fs:write-all",
"shell:execute",
"global-shortcut:allow-register"
]
}
]
}
}
}

Tauri v2 requires explicit permission declarations. If a command silently does nothing, check permissions first.

Common Rust patterns
// Get app data directory
let data_dir = app.path().app_data_dir().unwrap();

// Emit event to frontend
app_handle.emit("event-name", payload).ok();

// Get window
let window = app.get_webview_window("main").unwrap();

// App state
app.manage(MyState::new());
let state = app.state::<MyState>();


Notarization (macOS)
# Submit for notarization
xcrun notarytool submit app.dmg \
--apple-id YOUR_APPLE_ID \
--team-id YOUR_TEAM_ID \
--password YOUR_APP_PASSWORD \
--wait

# Staple after notarization
xcrun stapler staple app.dmg


Debugging
# Check what's in the bundle
unzip -l target/release/bundle/macos/App.app/Contents/MacOS/App

# Verify notarization
spctl -a -v App.app

# Check entitlements
codesign -d --entitlements - App.app


The most useful thing I learned

When a Tauri command silently fails: check the browser console first (Cmd+Option+I in dev mode), then check RUST_LOG output, then check permissions.

Silent failures in Tauri are almost always a permissions issue or a missing #[tauri::command] registration.

TL;DR: Quick Tauri v2 command reference: npm run tauri dev / tauri build -- --target universal-apple-darwin / tauri add <plugin>. Silent command failures? Check DevTools console → RUST_LOG → permissions in that order. Almost always a missing permission or unregistered command.

If this was useful, a ❤️ helps more than you'd think — thanks!

HiyokoAutoSync | X → @hiyoyok

via DEV Community: rust (author: hiyoyo)