Rust Implementation
This is the documentation of the Rust implementation of ivo.
Installation
$ cargo add ivo
How to use
ivo expects you to define your data model with structs that implement IvoInputStruct (required for input structs) and IvoStruct and this can be done via their respective derive macros as shown below.
use chrono::{DateTime, Utc};
use ivo::{IvoInputStruct, IvoStruct};
#[derive(Clone, PartailEq, IvoInputStruct)]
struct UserInput {
email: Option<String>,
phone_number: Option<String>,
username: String,
}
type Timestamp = DateTime<Utc>;
#[derive(Clone, PartailEq, IvoStruct)]
struct User {
id: String,
created_at: Timestamp,
email: Option<String>,
phone_number: Option<String>,
updated_at: Option<Timestamp>,
username: String,
username_last_updated_at: Option<Timestamp>,
}
IvoStruct
Deriving IvoStruct on User generates a struct called PartialUser together some helper methods for User and PartialUser.
-
User gets three helper methods with the following signatures:
impl IvoStruct for User {
fn append_updates(&mut self, updates: &Self::Partial);
fn clone_with_updates(&self, updates: &Self::Partial) -> Self;
}
impl From<User> for PartialUser {
fn from(value: User) -> PartialUser;
}
-
PartialUser has the signature:
struct PartialUser {
id: Option<String>,
created_at: Option<Timestamp>,
email: Option<String>,
phone_number: Option<Option<String>>,
updated_at: Option<Option<Timestamp>>,
username: Option<String>,
username_last_updated_at: Option<Option<Timestamp>>,
}
impl PartialUser {
fn new() -> Self;
fn set_id(&mut self, value: String) -> &mut Self;
fn with_id(mut self, value: String) -> Self;
fn set_username_last_updated_at(&mut self, value: Option<Timestamp>) -> &mut Self;
fn with_username_last_updated_at(mut self, value: Option<Timestamp>) -> Self;
fn unset_id(&mut self) -> &mut Self;
fn into_option(self) -> Option<Self>;
fn is_empty(&self) -> bool;
}
-
The #[ivo(...)] attribute can be used to customize PartialStructs and their fields.
#[derive(Clone, PartailEq, IvoInputStruct)]
#[ivo(derive(Serialize, Deserialize))]
struct UserInput {
email: Option<String>,
#[ivo(serde(skip_serializing_if = "Option::is_none"))]
phone_number: Option<String>,
username: String,
}
#[derive(Serialize, Deserialize)] struct PartialUserInput {
email: Option<Option<String>>,
#[serde(skip_serializing_if = "Option::is_none")] phone_number: Option<Option<String>>,
username: Option<String>,
}
IvoInputStruct
Deriving IvoInputStruct on UserInput automatically implements IvoStruct and generates two structs: PartialUserInput and UserInputErrors.
-
UserInputErrors is used to return errors from post-validators and grouped required resolvers and has the signature:
struct UserInputErrors {
email: Option<Option<String>>,
phone_number: Option<Option<String>>,
username: Option<String>,
}
impl UserInputErrors {
fn new() -> Self;
fn set_email(&mut self, reason: &str, metadata: Option<IvoErrorSanitizer::Metadata>) -> &mut Self;
fn with_email(mut self, reason: &str, metadata: Option<IvoErrorSanitizer::Metadata>) -> Self;
fn unset_email(&mut self) -> &mut Self;
fn into_option(self) -> Option<Self>;
fn is_empty(&self) -> bool;
}
Docs
Read the docs