Rust

Builder Pattern with Method Chaining

admin by @admin ADMIN
3d ago
May 31, 2026
Public
0 0 up · 0 down Sign in to vote
Construct complex objects step-by-step with `self`-returning methods. Type-state can enforce required vs. optional fields at compile time — but the simple version is plenty for most cases.
Rust
Raw
#[derive(Debug)]
struct Request {
    url:     String,
    method:  String,
    headers: Vec<(String, String)>,
    body:    Option<String>,
    timeout: u32,
}

#[derive(Default)]
struct RequestBuilder {
    url: Option<String>,
    method: String,
    headers: Vec<(String, String)>,
    body: Option<String>,
    timeout: u32,
}

impl RequestBuilder {
    fn url(mut self, url: impl Into<String>) -> Self { self.url = Some(url.into()); self }
    fn method(mut self, m: &str) -> Self { self.method = m.into(); self }
    fn header(mut self, k: &str, v: &str) -> Self {
        self.headers.push((k.into(), v.into())); self
    }
    fn body(mut self, b: impl Into<String>) -> Self { self.body = Some(b.into()); self }
    fn timeout(mut self, secs: u32) -> Self { self.timeout = secs; self }
    fn build(self) -> Result<Request, &'static str> {
        Ok(Request {
            url: self.url.ok_or("url is required")?,
            method: if self.method.is_empty() { "GET".into() } else { self.method },
            headers: self.headers,
            body: self.body,
            timeout: if self.timeout == 0 { 30 } else { self.timeout },
        })
    }
}

fn main() -> Result<(), &'static str> {
    let req = RequestBuilder::default()
        .url("https://api.example.com/users")
        .method("POST")
        .header("Content-Type", "application/json")
        .body(r#"{"name":"Alice"}"#)
        .timeout(10)
        .build()?;
    println!("{req:#?}");
    Ok(())
}
Tags

Save your own code snippets

Create a free account and build your private vault. Share publicly whenever you want.