use thisversion::traits::{IntoModel, IntoSchema};
use thisversion::{VersionBoundary, VersionFamily};
#[derive(VersionFamily)]
pub enum DocumentVersions<Content> {
V1(DocumentV1<Content>),
V2(DocumentV2<Content>),
V3(DocumentV3<Content>),
}
pub struct DocumentV1<Content> {
pub title: String,
pub body: Content,
}
pub struct DocumentV2<Content> {
pub title: String,
pub body: Content,
pub archived: bool,
}
impl<Content> From<DocumentV1<Content>> for DocumentV2<Content> {
fn from(previous: DocumentV1<Content>) -> Self {
Self {
title: previous.title,
body: previous.body,
archived: false,
}
}
}
#[derive(VersionBoundary)]
#[thisversion(model = Document<Content>)]
pub struct DocumentV3<Content> {
pub title: String,
pub content: Content,
pub archived: bool,
}
impl<Content> From<DocumentV2<Content>> for DocumentV3<Content> {
fn from(previous: DocumentV2<Content>) -> Self {
Self {
title: previous.title,
content: previous.body,
archived: previous.archived,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Document<Content> {
pub title: String,
pub content: Content,
pub archived: bool,
}
#[derive(Debug, PartialEq, Eq)]
struct RichText {
spans: Vec<TextSpan>,
}
#[derive(Debug, PartialEq, Eq)]
struct TextSpan {
text: String,
bold: bool,
}
fn main() {
let markdown = DocumentVersions::V1(DocumentV1 {
title: "Getting started".to_owned(),
body: "Read the **installation guide**.".to_owned(),
});
let markdown: Document<String> = markdown.into_model();
assert_eq!(
markdown,
Document {
title: "Getting started".to_owned(),
content: "Read the **installation guide**.".to_owned(),
archived: false,
}
);
let rich_text = DocumentVersions::V2(DocumentV2 {
title: "Release announcement".to_owned(),
body: RichText {
spans: vec![
TextSpan {
text: "Introducing ".to_owned(),
bold: false,
},
TextSpan {
text: "our new editor".to_owned(),
bold: true,
},
],
},
archived: true,
});
let rich_text: Document<RichText> = rich_text.into_model();
assert_eq!(
rich_text,
Document {
title: "Release announcement".to_owned(),
content: RichText {
spans: vec![
TextSpan {
text: "Introducing ".to_owned(),
bold: false,
},
TextSpan {
text: "our new editor".to_owned(),
bold: true,
},
],
},
archived: true,
}
);
let markdown: DocumentVersions<String> = markdown.into_schema();
let rich_text: DocumentVersions<RichText> = rich_text.into_schema();
assert!(matches!(markdown, DocumentVersions::V3(_)));
assert!(matches!(rich_text, DocumentVersions::V3(_)));
}