use thisversion::traits::{IntoModel, IntoSchema};
pub enum DocumentVersions {
V1(DocumentV1),
V2(DocumentV2),
V3(DocumentV3),
}
impl IntoModel for DocumentVersions {
type Model = Document;
fn into_model(self) -> Self::Model {
match self {
Self::V1(v1) => Self::V2(DocumentV2::from(v1)).into_model(),
Self::V2(v2) => Self::V3(DocumentV3::from(v2)).into_model(),
Self::V3(v3) => v3.into_model(),
}
}
}
pub struct DocumentV1 {
pub title: String,
pub body: String,
}
pub struct DocumentV2 {
pub title: String,
pub body: String,
pub archived: bool,
}
impl From<DocumentV1> for DocumentV2 {
fn from(prev: DocumentV1) -> Self {
Self {
title: prev.title,
body: prev.body,
archived: false,
}
}
}
pub struct DocumentV3 {
pub title: String,
pub content: String,
pub archived: bool,
}
impl From<DocumentV2> for DocumentV3 {
fn from(prev: DocumentV2) -> Self {
Self {
title: prev.title,
content: prev.body,
archived: prev.archived,
}
}
}
impl IntoModel for DocumentV3 {
type Model = Document;
fn into_model(self) -> Self::Model {
Document {
title: self.title,
content: self.content,
archived: self.archived,
}
}
}
impl IntoSchema<DocumentVersions> for Document {
fn into_schema(self) -> DocumentVersions {
DocumentVersions::V3(DocumentV3 {
title: self.title,
content: self.content,
archived: self.archived,
})
}
}
pub struct Document {
pub title: String,
pub content: String,
pub archived: bool,
}
fn main() {
let v1 = DocumentV1 {
title: "Hello".to_owned(),
body: "Hello, world!".to_owned(),
};
let versions = DocumentVersions::V1(v1);
let document = versions.into_model();
assert_eq!(document.title, "Hello");
assert_eq!(document.content, "Hello, world!");
assert!(!document.archived);
let versions = document.into_schema();
assert!(matches!(versions, DocumentVersions::V3(_)));
let reloaded = versions.into_model();
assert_eq!(reloaded.content, "Hello, world!");
}