For example let's say that I have written an HTTP API that accepts application/x-www-form-urlencoded data to one of its endpoints. Let's say `POST /users`, and this is where the client-side application posts data to.
Now I can implement this in many ways. I can for example define
pub struct Person {
name: String,
phone_number: String,
}
But how I populate this struct can determine whether I am actually parsing or not, even if most of the code aside from that is the same.And of course I could go further and define types for the name and the phone number but in this case lets say that I have decided that strings are the proper representation in this case.
If the fields of my structs were directly accessible
pub struct Person {
pub name: String,
pub phone_number: String,
}
And in my HTTP API endpoint for `POST /users` I do the following: // ...
let name = post_data.name;
let phone_number = post_data.phone_number;
let norwegian_phone_number_format = Regex::new(r"^(\+47|0047)?\d{8}$").unwrap();
// ...
And I didn't bother to write out the rest of the code here for this example but you get the gist.The point is that here I am doing some rudimentary validation on the phone number, requiring it to be in Norwegian format. But I am enforcing this in the implementation of the handler for the HTTP API endpoint, rather than in the data type itself.
Whereas if I was instead doing
pub struct Person {
name: String,
phone_number: String,
}
impl Person {
pub fn try_new (name: String, phone_number: String) -> std::result::Result<Self, PersonDataError> {
// ...
let norwegian_phone_number_format = Regex::new(r"^(\+47|0047)?\d{8}$").unwrap();
// ...
}
}
Now I've moved the validation into an associated function of the type itself, and I've made the fields of the struct unaccessible from the outside.And in this manner, even though my validation is still rudimentary, and a type purist might find the type insufficiently constrained, I have indeed in my own book gone from just validation to actual parsing. Because I have made it so that the construction of the type enforces the constraints on the data.