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:
Trait implementation: You can implement traits on a unit struct. This is the
primary reason for using this pattern. For example, you could implement a
Handler, Strategy, or Factory trait on Foo. Something you can’t do on
loose functions.
It can be passed as a value: Foo is a concrete type, so you can pass it to
functions that expect a generic T bounded by some trait. Or you can use it
in a collection.
It signals intent: Grouping methods on a struct signals that they are conceptually related in a way that’s more explicit than just a module.
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.