Rust Namespace Pattern




Rust doesn’t provide namespaces, nor does it have static classes. If you want to group related functions under a named “thing”, without any actual data, a unit struct is the idiomatic way to accomplish this. Essentially the struct is being used as a logical container or namespace for the functions. The pattern is also known as a Unit Struct pattern, or a Zero-Sized Type (ZST) facade.

Here’s what it looks like:

pub struct Foo;

impl Foo {
    pub fn bar() -> i32 { 43 }
    pub fn baz() -> &'static str { "hello" }
}

You could just have free functions in a module, but the unit struct pattern has some specific advantages:

The zero-sized part matters. Because Foo holds no data, it costs nothing at runtime. std::mem::size_of::<Foo>() is 0. The compiler may eliminate any instance of it, so it’s a pure compile-time organizational tool with no overhead.

A real world example using the marker/strategy pattern

pub struct JsonSerializer;
pub struct XmlSerializer;

trait Serializer {
    fn serialize(data: &str) -> String;
}

impl Serializer for JsonSerializer {
    fn serialize(data: &str) -> String { format!("{{\"data\": \"{}\"}}", data) }
}

impl Serializer for XmlSerializer {
    fn serialize(data: &str) -> String { format!("<data>{}</data>", data) }
}

Now you can write generic code over T: Serializer and swap implementations at compile time with zero runtime costs.

To summarize: a unit struct, also called a ZST namespace/facade pattern, is used for trait implementation, type-level polymorphism, and logical grouping. All with zero runtime cost.