use chrono::{DateTime, Utc};
use simple_dto_mapper_derive::DtoFrom;
mod types {
use chrono::{DateTime, Utc};
pub struct User {
pub id: String,
pub name: String,
pub age: u32,
pub password: String, pub note: Option<String>,
pub status: SourceStatus,
pub rank: Rank,
pub level: i32,
pub created_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone)]
pub enum SourceStatus {
Active,
Inactive,
}
#[derive(Debug, Clone)]
pub enum DtoStatus {
Active,
Inactive,
}
impl From<SourceStatus> for DtoStatus {
fn from(s: SourceStatus) -> Self {
match s {
SourceStatus::Active => DtoStatus::Active,
SourceStatus::Inactive => DtoStatus::Inactive,
}
}
}
#[allow(dead_code)]
pub fn mask_name(name: String) -> String {
let first = name.chars().next().unwrap_or('*');
format!("{}***", first)
}
#[derive(Debug, Clone)]
pub enum Rank {
Junior,
Senior,
}
impl core::convert::TryFrom<i32> for Rank {
type Error = &'static str;
fn try_from(v: i32) -> Result<Self, Self::Error> {
match v {
0 => Ok(Rank::Junior),
1 => Ok(Rank::Senior),
_ => Err("unknown rank"),
}
}
}
impl Default for Rank {
fn default() -> Self {
Rank::Junior
}
}
}
use types::{SourceStatus, User};
#[derive(Debug, DtoFrom)]
#[dto(from = types::User)]
pub struct UserDto {
pub id: String,
#[dto(rename = "name", transform_fn = types::mask_name)]
pub display_name: String,
pub age: u32,
pub note: Option<String>,
#[dto(skip)]
pub note2: Option<String>,
#[dto(into)]
pub status: types::DtoStatus,
pub rank: types::Rank,
pub created_at: Option<DateTime<Utc>>,
}
fn main() {
let user = User {
id: "u123".to_string(),
name: "Alice".to_string(),
age: 30,
password: "supersecret".to_string(),
note: Some("note".to_string()),
status: SourceStatus::Active,
rank: types::Rank::Senior,
level: 1,
created_at: Some(Utc::now()),
};
let dto: UserDto = user.into();
println!("Mapped DTO (owned): {:?}", dto);
}