Then give it a constructor (which in rust is just a regular static function) that checks the non-zero variant. You can define method on this type, and make it implement traits (which are kind of like interfaces).
The best bit: there is zero runtime cost to this, the memory-representation of this type is identical to that of the underlying u32.
Rust-style enums which can contain data, and also have method implemented on them are even better. Doesn't mean classes (structs in Rust) aren't useful, but once you use a language that allows you to define other kinds of custom types, they seem very restrictive when they're the only available tool.
Yep. This whole discussion just seems like a C vs C++ styleguide slapfight.
Having the functions that operate on the struct attached directly to the struct declaration, vs having some functions that the first parameter is the struct on which the function operates, doesn't seem like a particularly meaningful distinction to me. OK, you like C-style programming in favor of C++-style programming, congrats. It's still a class either way.
The distinction you describe is not meaningful, but the key feature that separates classes from other forms of code organization/polymorphism, like typeclasses as in Haskell/Rust, is not that. It is inheritance.
I guess it's kind close to a C++ class. It's pretty different to a class in a language like Java, because all classes in Java are heap allocated and behind references.
Enums are are the better example of non-class types. For example, you can have:
enum StringOrInt {
String(String),
Int(u32),
}
And you can go ahead and implement methods on that type. Classes have "AND-state", not "OR-state". But a Type in general can have either kind of state.
That's equivalent to wrapping an enum in a class. Emulations of type hierarchies without OO often fail like this, having a A-or-B be literally the same type so losing out on type safety/forcing constant rechecking of the discriminant.
The best bit: there is zero runtime cost to this, the memory-representation of this type is identical to that of the underlying u32.
Rust-style enums which can contain data, and also have method implemented on them are even better. Doesn't mean classes (structs in Rust) aren't useful, but once you use a language that allows you to define other kinds of custom types, they seem very restrictive when they're the only available tool.