🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 12 Min Lesezeit
0

Rust Concepts: dyn Trait, Custom Iterators, Deref/Drop & Axum REST API (Part 5)

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

This is Part 5 of the Core Rust Concepts series.





  • Part 1 — Ownership, Borrowing, Lifetimes, Traits, Result/Option, Pattern Matching


  • Part 2 — Closures, Iterators, Generics, Enums, Smart Pointers, Async/Await


  • Part 3 — Macros, Modules, Testing, Unsafe Rust, FFI


  • Part 4 — Threads, Channels, Send/Sync, Mutex, Atomics, clap










Table of Contents




  1. Trait Objects and Dynamic Dispatch

  2. The Deref Trait

  3. The Drop Trait

  4. Custom Iterators

  5. Building a REST API with Axum









25. Trait Objects and Dynamic Dispatch



In Part 2 we used impl Trait — that's static dispatch: the compiler knows the exact type at compile time and monomorphizes it. Sometimes you don't know the type until runtime. That's where trait objects (dyn Trait) come in.






Static vs Dynamic dispatch






CODE
trait Greet {
fn hello(&self) -> String;
}

struct English;
struct Spanish;

impl Greet for English {
fn hello(&self) -> String { String::from("Hello!") }
}

impl Greet for Spanish {
fn hello(&self) -> String { String::from("¡Hola!") }
}

// Static dispatch — type known at compile time, zero overhead
fn greet_static(g: &impl Greet) {
println!("{}", g.hello());
}

// Dynamic dispatch — type known at runtime via vtable
fn greet_dynamic(g: &dyn Greet) {
println!("{}", g.hello());
}

fn main() {
let e = English;
let s = Spanish;

greet_static(&e);
greet_dynamic(&s);

// Only dyn Trait allows mixing types in a collection
let greeters: Vec<Box<dyn Greet>> = vec![
Box::new(English),
Box::new(Spanish),
Box::new(English),
];

for g in &greeters {
println!("{}", g.hello());
}
}









When to use dyn Trait vs impl Trait






































impl Trait dyn Trait
Dispatch Static (compile time) Dynamic (runtime vtable)
Performance Zero overhead Small indirection cost
Heterogeneous collections
Return from function ✅ (one concrete type) ✅ (any type at runtime)
Sized ❌ (must be behind & or Box)





Object-safe traits



Not every trait can be made into a trait object. A trait is object-safe if:




  • It has no methods that return Self

  • It has no generic methods




CODE
// ✅ Object-safe
trait Drawable {
fn draw(&self);
fn area(&self) -> f64;
}

// ❌ NOT object-safe — returns Self
trait Clone2 {
fn clone2(&self) -> Self; // can't use as dyn Clone2
}









Real-world pattern — plugin system






CODE
trait Plugin {
fn name(&self) -> &str;
fn run(&self, input: &str) -> String;
}

struct UppercasePlugin;
struct ReversePlugin;

impl Plugin for UppercasePlugin {
fn name(&self) -> &str { "uppercase" }
fn run(&self, input: &str) -> String { input.to_uppercase() }
}

impl Plugin for ReversePlugin {
fn name(&self) -> &str { "reverse" }
fn run(&self, input: &str) -> String { input.chars().rev().collect() }
}

struct Pipeline {
plugins: Vec<Box<dyn Plugin>>,
}

impl Pipeline {
fn new() -> Self { Self { plugins: vec![] } }

fn add(mut self, p: Box<dyn Plugin>) -> Self {
self.plugins.push(p);
self
}

fn run(&self, input: &str) -> String {
self.plugins.iter().fold(input.to_string(), |acc, p| p.run(&acc))
}
}

fn main() {
let pipeline = Pipeline::new()
.add(Box::new(UppercasePlugin))
.add(Box::new(ReversePlugin));

println!("{}", pipeline.run("hello")); // "OLLEH"
}












26. The Deref Trait



Deref controls what happens when you use the * operator on a type. It's also what enables deref coercions — Rust automatically calls deref() to convert types so you don't have to do it manually.




CODE
use std::ops::Deref;

// A simple smart pointer
struct MyBox<T>(T);

impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> { MyBox(x) }
}

impl<T> Deref for MyBox<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0 // return a reference to the inner value
}
}

fn hello(name: &str) {
println!("Hello, {name}!");
}

fn main() {
let x = MyBox::new(String::from("Rustacean"));

// These are all equivalent due to deref coercions:
hello(&x); // MyBox<String> → &String → &str (auto!)
hello(&(*x)[..]); // manual — what Rust does behind the scenes
hello(x.deref()); // explicit deref
}









Deref coercion chain



Rust automatically chains Deref calls as many times as needed:




CODE
MyBox<String>  →  String  →  str
&MyBox<String> → &String → &str









CODE
fn main() {
let boxed = Box::new(String::from("hello"));

// Box<String> derefs to String, then to str
println!("{}", boxed.to_uppercase()); // HELLO
println!("{}", boxed.len()); // 5

let s: &str = &boxed; // Box<String> → &String → &str — all automatic
println!("{s}");
}









DerefMut



DerefMut does the same for mutable contexts:




CODE
use std::ops::{Deref, DerefMut};

struct Wrapper(Vec<i32>);

impl Deref for Wrapper {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> { &self.0 }
}

impl DerefMut for Wrapper {
fn deref_mut(&mut self) -> &mut Vec<i32> { &mut self.0 }
}

fn main() {
let mut w = Wrapper(vec![1, 2, 3]);
w.push(4); // DerefMut lets you call Vec methods
println!("{:?}", w.as_slice()); // Deref: [1, 2, 3, 4]
}












27. The Drop Trait



Drop lets you run custom cleanup code when a value goes out of scope — like a destructor in C++. Rust calls drop() automatically; you never call it yourself (use std::mem::drop() to drop early).




CODE
struct Resource {
name: String,
}

impl Resource {
fn new(name: &str) -> Self {
println!("acquiring: {name}");
Resource { name: name.to_string() }
}
}

impl Drop for Resource {
fn drop(&mut self) {
println!("releasing: {}", self.name);
}
}

fn main() {
let _a = Resource::new("database connection");
let _b = Resource::new("file handle");
println!("resources in use...");
// Drop order is LIFO: _b dropped first, then _a
}






Output:




CODE
acquiring: database connection
acquiring: file handle
resources in use...
releasing: file handle
releasing: database connection









Dropping early






CODE
fn main() {
let conn = Resource::new("db");
println!("doing work...");

drop(conn); // explicit early drop — calls Drop::drop()
println!("conn already released");

// conn.name; ← compile error: value was dropped
}









Drop in practice — RAII pattern






CODE
use std::sync::{Arc, Mutex};

struct DbPool {
connections: Arc<Mutex<Vec<String>>>,
}

struct DbConnection {
id: String,
pool: Arc<Mutex<Vec<String>>>,
}

impl Drop for DbConnection {
fn drop(&mut self) {
// Return the connection back to the pool automatically
self.pool.lock().unwrap().push(self.id.clone());
println!("connection '{}' returned to pool", self.id);
}
}

impl DbPool {
fn new() -> Self {
let conns = vec!["conn-1".into(), "conn-2".into(), "conn-3".into()];
Self { connections: Arc::new(Mutex::new(conns)) }
}

fn get(&self) -> Option<DbConnection> {
let id = self.connections.lock().unwrap().pop()?;
println!("checked out: {id}");
Some(DbConnection { id, pool: Arc::clone(&self.connections) })
}
}

fn main() {
let pool = DbPool::new();
{
let _c1 = pool.get(); // "conn-3"
let _c2 = pool.get(); // "conn-2"
} // both returned to pool here automatically
println!("pool size: {}", pool.connections.lock().unwrap().len()); // 3
}







🦀 This is the RAII (Resource Acquisition Is Initialization) pattern — the same one Rust's MutexGuard, file handles, and socket wrappers use internally.










28. Custom Iterators



You can make any type iterable by implementing the Iterator trait, which requires only one method: next().




CODE
struct Counter {
count: u32,
max: u32,
}

impl Counter {
fn new(max: u32) -> Self { Self { count: 0, max } }
}

impl Iterator for Counter {
type Item = u32;

fn next(&mut self) -> Option<Self::Item> {
if self.count < self.max {
self.count += 1;
Some(self.count)
} else {
None // signals the iterator is exhausted
}
}
}

fn main() {
let counter = Counter::new(5);

// You get ALL iterator methods for free!
let sum: u32 = counter.sum();
println!("sum: {sum}"); // 15

// Chain with other iterators
let result: Vec<u32> = Counter::new(5)
.zip(Counter::new(5).skip(1)) // pair consecutive values
.map(|(a, b)| a * b) // multiply each pair
.filter(|x| x % 3 == 0) // keep multiples of 3
.collect();

println!("{:?}", result); // [6, 12]
}









A real-world custom iterator — paginated results






CODE
struct Paginator {
current_page: u32,
total_pages: u32,
page_size: u32,
}

impl Paginator {
fn new(total_items: u32, page_size: u32) -> Self {
Self {
current_page: 0,
total_pages: (total_items + page_size - 1) / page_size,
page_size,
}
}
}

#[derive(Debug)]
struct Page {
number: u32,
offset: u32,
limit: u32,
}

impl Iterator for Paginator {
type Item = Page;

fn next(&mut self) -> Option<Page> {
if self.current_page < self.total_pages {
self.current_page += 1;
Some(Page {
number: self.current_page,
offset: (self.current_page - 1) * self.page_size,
limit: self.page_size,
})
} else {
None
}
}
}

fn main() {
let pages = Paginator::new(95, 20);

for page in pages {
println!("Page {}: OFFSET {} LIMIT {}", page.number, page.offset, page.limit);
}
}






Output:




CODE
Page 1: OFFSET 0 LIMIT 20
Page 2: OFFSET 20 LIMIT 20
Page 3: OFFSET 40 LIMIT 20
Page 4: OFFSET 60 LIMIT 20
Page 5: OFFSET 80 LIMIT 20









IntoIterator — making structs work in for loops






CODE
struct Stack<T> {
items: Vec<T>,
}

impl<T> Stack<T> {
fn new() -> Self { Self { items: vec![] } }
fn push(&mut self, item: T) { self.items.push(item); }
}

impl<T> IntoIterator for Stack<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;

fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}

fn main() {
let mut stack = Stack::new();
stack.push(1);
stack.push(2);
stack.push(3);

for item in stack { // works because of IntoIterator
println!("{item}");
}
}












29. Building a REST API with Axum



axum is the most popular async web framework in Rust, built on top of tokio and hyper. It uses Rust's type system to make routing and request extraction ergonomic and safe.






Setup






CODE
# Cargo.toml
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
uuid = { version = "1", features = ["v4"] }









Full CRUD API — Todo List






CODE
use axum::{
extract::{Path, State},
http::StatusCode,
response::Json,
routing::{delete, get, post, put},
Router,
};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
use uuid::Uuid;

// --- Models ---

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Todo {
id: String,
title: String,
completed: bool,
}

#[derive(Deserialize)]
struct CreateTodo {
title: String,
}

#[derive(Deserialize)]
struct UpdateTodo {
title: Option<String>,
completed: Option<bool>,
}

// --- Shared state ---

type Db = Arc<Mutex<Vec<Todo>>>;

// --- Handlers ---

async fn list_todos(State(db): State<Db>) -> Json<Vec<Todo>> {
let todos = db.lock().unwrap();
Json(todos.clone())
}

async fn create_todo(
State(db): State<Db>,
Json(payload): Json<CreateTodo>,
) -> (StatusCode, Json<Todo>) {
let todo = Todo {
id: Uuid::new_v4().to_string(),
title: payload.title,
completed: false,
};
db.lock().unwrap().push(todo.clone());
(StatusCode::CREATED, Json(todo))
}

async fn get_todo(
State(db): State<Db>,
Path(id): Path<String>,
) -> Result<Json<Todo>, StatusCode> {
let todos = db.lock().unwrap();
todos
.iter()
.find(|t| t.id == id)
.cloned()
.map(Json)
.ok_or(StatusCode::NOT_FOUND)
}

async fn update_todo(
State(db): State<Db>,
Path(id): Path<String>,
Json(payload): Json<UpdateTodo>,
) -> Result<Json<Todo>, StatusCode> {
let mut todos = db.lock().unwrap();
let todo = todos.iter_mut().find(|t| t.id == id).ok_or(StatusCode::NOT_FOUND)?;

if let Some(title) = payload.title { todo.title = title; }
if let Some(completed) = payload.completed { todo.completed = completed; }

Ok(Json(todo.clone()))
}

async fn delete_todo(
State(db): State<Db>,
Path(id): Path<String>,
) -> StatusCode {
let mut todos = db.lock().unwrap();
let before = todos.len();
todos.retain(|t| t.id != id);

if todos.len() < before { StatusCode::NO_CONTENT }
else { StatusCode::NOT_FOUND }
}

// --- Router ---

fn app(db: Db) -> Router {
Router::new()
.route("/todos", get(list_todos).post(create_todo))
.route("/todos/:id", get(get_todo).put(update_todo).delete(delete_todo))
.with_state(db)
}

// --- Main ---

#[tokio::main]
async fn main() {
let db: Db = Arc::new(Mutex::new(vec![]));

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
println!("listening on http://localhost:3000");

axum::serve(listener, app(db)).await.unwrap();
}









Test it with curl






CODE
# Create todos
curl -s -X POST http://localhost:3000/todos \
-H "Content-Type: application/json" \
-d '{"title": "Learn Rust"}' | jq

curl -s -X POST http://localhost:3000/todos \
-H "Content-Type: application/json" \
-d '{"title": "Build an API"}' | jq

# List all
curl -s http://localhost:3000/todos | jq

# Get one (replace ID)
curl -s http://localhost:3000/todos/<id> | jq

# Update
curl -s -X PUT http://localhost:3000/todos/<id> \
-H "Content-Type: application/json" \
-d '{"completed": true}' | jq

# Delete
curl -s -X DELETE http://localhost:3000/todos/<id>









Adding middleware — request logging






CODE
use axum::middleware::{self, Next};
use axum::extract::Request;
use axum::response::Response;

async fn log_request(req: Request, next: Next) -> Response {
let method = req.method().clone();
let uri = req.uri().clone();
let res = next.run(req).await;
println!("{} {} → {}", method, uri, res.status());
res
}

fn app(db: Db) -> Router {
Router::new()
.route("/todos", get(list_todos).post(create_todo))
.route("/todos/:id", get(get_todo).put(update_todo).delete(delete_todo))
.layer(middleware::from_fn(log_request)) // add logging to all routes
.with_state(db)
}












Wrapping Up
































Concept What it gives you
dyn Trait Runtime polymorphism, heterogeneous collections
Deref Transparent smart pointer ergonomics, auto-coercions
Drop RAII — deterministic cleanup, no GC needed
Custom iterators Any type can plug into Rust's iterator ecosystem
Axum Type-safe, async REST APIs on top of tokio








The full series
































Part Topics
Part 1 Ownership, Borrowing, Lifetimes, Traits, Result/Option, Pattern Matching
Part 2 Closures, Iterators, Generics, Enums, Smart Pointers, Async/Await
Part 3 Macros, Modules, Cargo, Testing, Unsafe, FFI
Part 4 Threads, Channels, Send/Sync, Mutex, Atomics, clap
Part 5 dyn Trait, Deref, Drop, Custom Iterators, Axum REST API








What's in Part 6?




  • Workspaces and multi-crate projects


  • serde — serialization deep dive

  • Benchmarking with criterion

  • Error handling patterns with thiserror and anyhow

  • Writing a real-world CLI + library crate






Found this useful? Drop a ❤️ and follow for Part 6!

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Rust Concepts: dyn Trait, Custom Iterators, Deref/Drop & Axum REST API (Part 5)

Thematisch verwandte Begriffe: Rust, Concepts, Trait, Custom · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...