feat: AutoFrom

This commit is contained in:
Artemy Egorov 2024-08-03 12:47:33 +03:00
parent fd698859b8
commit 5058bb812b
5 changed files with 149 additions and 164 deletions

11
Cargo.lock generated
View file

@ -196,6 +196,7 @@ dependencies = [
"bincode", "bincode",
"chumsky", "chumsky",
"clap", "clap",
"enum-procs",
"flate2", "flate2",
"num_enum", "num_enum",
"rmp-serde", "rmp-serde",
@ -204,6 +205,16 @@ dependencies = [
"zstd", "zstd",
] ]
[[package]]
name = "enum-procs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e188616f4527e2cf6128e58622bb2fd16ebcfa37a200b2d16739c3ca227bf649"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"

View file

@ -18,6 +18,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_repr = "0.1" serde_repr = "0.1"
zstd = "0.13.2" zstd = "0.13.2"
chumsky = { version = "=1.0.0-alpha.7", features = ["label"], optional = true } chumsky = { version = "=1.0.0-alpha.7", features = ["label"], optional = true }
enum-procs = "0.3.0"
[dev-dependencies] [dev-dependencies]
rmp-serde = { version = "1.3.0" } rmp-serde = { version = "1.3.0" }

View file

@ -1,7 +1,9 @@
use enum_procs::AutoFrom;
use num_enum::TryFromPrimitive;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_repr::{Deserialize_repr, Serialize_repr};
use num_enum::TryFromPrimitive; pub type Root = Vec<Tag>;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct Tag { pub struct Tag {
@ -22,7 +24,7 @@ pub fn t_new(id: Tid, body: Body, argument: Argument) -> Tag {
Tag::new(id, body, argument) Tag::new(id, body, argument)
} }
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(untagged)] #[serde(untagged)]
pub enum Body { pub enum Body {
Text(String), Text(String),
@ -30,7 +32,7 @@ pub enum Body {
Null, Null,
} }
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(untagged)] #[serde(untagged)]
pub enum Argument { pub enum Argument {
Text(String), Text(String),
@ -96,22 +98,7 @@ pub trait IsNull {
fn is_null(&self) -> bool; fn is_null(&self) -> bool;
} }
pub trait ToDaletl { pub trait ToDaletlRoot {
/// Convert to daletl root /// Convert to daletl root
fn to_dl(self) -> Vec<Tag>; fn to_dl_root(self) -> Root;
}
pub trait ToDaletlTag {
/// Convert to daletl tag
fn to_dl_tag(self) -> Tag;
}
pub trait ToDaletlBody {
/// Convert to daletl body
fn to_dl_body(self) -> Body;
}
pub trait ToDaletlArgument {
/// Convert to daletl arg
fn to_dl_arg(self) -> Argument;
} }

View file

@ -1,10 +1,13 @@
use enum_procs::AutoFrom;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use crate::daletl::{self, t_new, Tid, ToDaletl, ToDaletlArgument, ToDaletlBody, ToDaletlTag}; use crate::daletl::{self, t_new, Tid, ToDaletlRoot};
const NB: daletl::Body = daletl::Body::Null; const NB: daletl::Body = daletl::Body::Null;
const NA: daletl::Argument = daletl::Argument::Null; const NA: daletl::Argument = daletl::Argument::Null;
pub type Root = Vec<Tag>;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Tag { pub enum Tag {
El(NNBody), El(NNBody),
@ -39,39 +42,39 @@ pub enum Tag {
Pre(String), Pre(String),
} }
impl ToDaletlTag for Tag { impl From<Tag> for daletl::Tag {
fn to_dl_tag(self) -> daletl::Tag { fn from(item: Tag) -> daletl::Tag {
match self { match item {
Tag::El(b) => t_new(Tid::El, b.to_dl_body(), NA), Tag::El(b) => t_new(Tid::El, b.into(), NA),
Tag::H(b, a) => t_new(Tid::H, b.to_dl_body(), a.to_dl_arg()), Tag::H(b, a) => t_new(Tid::H, b.into(), a.into()),
Tag::P(b) => t_new(Tid::P, b.to_dl_body(), NA), Tag::P(b) => t_new(Tid::P, b.into(), NA),
Tag::Br => t_new(Tid::Br, NB, NA), Tag::Br => t_new(Tid::Br, NB, NA),
Tag::Ul(b) => t_new(Tid::Ul, b.to_dl_body(), NA), Tag::Ul(b) => t_new(Tid::Ul, b.into(), NA),
Tag::Ol(b) => t_new(Tid::Ol, b.to_dl_body(), NA), Tag::Ol(b) => t_new(Tid::Ol, b.into(), NA),
Tag::Row(b, a) => t_new(Tid::Row, b.to_dl_body(), a.to_dl_arg()), Tag::Row(b, a) => t_new(Tid::Row, b.into(), a.into()),
Tag::Link(b, a) => t_new(Tid::Link, b.to_dl_body(), a.to_dl_arg()), Tag::Link(b, a) => t_new(Tid::Link, b.into(), a.into()),
Tag::Navlink(b, a) => t_new(Tid::Navlink, b.to_dl_body(), a.to_dl_arg()), Tag::Navlink(b, a) => t_new(Tid::Navlink, b.into(), a.into()),
Tag::Btn(b, a) => t_new(Tid::Btn, b.to_dl_body(), a.to_dl_arg()), Tag::Btn(b, a) => t_new(Tid::Btn, b.into(), a.into()),
Tag::Navbtn(b, a) => t_new(Tid::Navbtn, b.to_dl_body(), a.to_dl_arg()), Tag::Navbtn(b, a) => t_new(Tid::Navbtn, b.into(), a.into()),
Tag::Img(a) => t_new(Tid::Img, NB, a.to_dl_arg()), Tag::Img(a) => t_new(Tid::Img, NB, a.into()),
Tag::Table(b) => t_new(Tid::Table, b.to_dl_body(), NA), Tag::Table(b) => t_new(Tid::Table, b.into(), NA),
Tag::Tcol(b) => t_new(Tid::Tcol, b.to_dl_body(), NA), Tag::Tcol(b) => t_new(Tid::Tcol, b.into(), NA),
Tag::Tpcol(b) => t_new(Tid::Tpcol, b.to_dl_body(), NA), Tag::Tpcol(b) => t_new(Tid::Tpcol, b.into(), NA),
Tag::Hr => t_new(Tid::Hr, NB, NA), Tag::Hr => t_new(Tid::Hr, NB, NA),
Tag::B(b) => t_new(Tid::B, b.to_dl_body(), NA), Tag::B(b) => t_new(Tid::B, b.into(), NA),
Tag::I(b) => t_new(Tid::I, b.to_dl_body(), NA), Tag::I(b) => t_new(Tid::I, b.into(), NA),
Tag::Bq(b) => t_new(Tid::Bq, b.to_dl_body(), NA), Tag::Bq(b) => t_new(Tid::Bq, b.into(), NA),
Tag::Footlnk(a) => t_new(Tid::Footlnk, NB, a.to_dl_arg()), Tag::Footlnk(a) => t_new(Tid::Footlnk, NB, a.into()),
Tag::Footn(b, a) => t_new(Tid::Footn, b.to_dl_body(), a.to_dl_arg()), Tag::Footn(b, a) => t_new(Tid::Footn, b.into(), a.into()),
Tag::A(a) => t_new(Tid::A, NB, a.to_dl_arg()), Tag::A(a) => t_new(Tid::A, NB, a.into()),
Tag::S(b) => t_new(Tid::S, b.to_dl_body(), NA), Tag::S(b) => t_new(Tid::S, b.into(), NA),
Tag::Sup(b) => t_new(Tid::Sup, b.to_dl_body(), NA), Tag::Sup(b) => t_new(Tid::Sup, b.into(), NA),
Tag::Sub(b) => t_new(Tid::Sub, b.to_dl_body(), NA), Tag::Sub(b) => t_new(Tid::Sub, b.into(), NA),
Tag::Disc(b) => t_new(Tid::Disc, b.to_dl_body(), NA), Tag::Disc(b) => t_new(Tid::Disc, b.into(), NA),
Tag::Bl(b, a) => t_new(Tid::Bl, b.to_dl_body(), a.to_dl_arg()), Tag::Bl(b, a) => t_new(Tid::Bl, b.into(), a.into()),
Tag::Carousel(b) => t_new(Tid::Carousel, b.to_dl_body(), NA), Tag::Carousel(b) => t_new(Tid::Carousel, b.into(), NA),
Tag::Code(s, a) => t_new(Tid::Code, s.to_dl_body(), a.to_dl_arg()), Tag::Code(s, a) => t_new(Tid::Code, s.into(), a.into()),
Tag::Pre(s) => t_new(Tid::Pre, s.to_dl_body(), NA), Tag::Pre(s) => t_new(Tid::Pre, s.into(), NA),
} }
} }
} }
@ -88,15 +91,15 @@ pub enum Hl {
Six, Six,
} }
impl ToDaletlArgument for Hl { impl From<Hl> for daletl::Argument {
fn to_dl_arg(self) -> daletl::Argument { fn from(item: Hl) -> daletl::Argument {
match self { match item {
Hl::One => NA, Hl::One => NA,
Hl::Two => 2u8.to_dl_arg(), Hl::Two => 2u8.into(),
Hl::Three => 3u8.to_dl_arg(), Hl::Three => 3u8.into(),
Hl::Four => 4u8.to_dl_arg(), Hl::Four => 4u8.into(),
Hl::Five => 5u8.to_dl_arg(), Hl::Five => 5u8.into(),
Hl::Six => 6u8.to_dl_arg(), Hl::Six => 6u8.into(),
} }
} }
} }
@ -109,122 +112,104 @@ pub enum AlignArgument {
End, End,
} }
impl ToDaletlArgument for AlignArgument { impl From<AlignArgument> for daletl::Argument {
fn to_dl_arg(self) -> daletl::Argument { fn from(item: AlignArgument) -> daletl::Argument {
match self { match item {
Self::Start => NA, AlignArgument::Start => NA,
Self::Center => 1u8.to_dl_arg(), AlignArgument::Center => 1u8.into(),
Self::End => 2u8.to_dl_arg(), AlignArgument::End => 2u8.into(),
} }
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Debug, Clone, PartialEq, Eq)]
pub enum TNArgument { pub enum TNArgument {
Text(String), Text(String),
Null, Null,
} }
impl ToDaletlArgument for TNArgument { impl From<TNArgument> for daletl::Argument {
fn to_dl_arg(self) -> daletl::Argument { fn from(item: TNArgument) -> daletl::Argument {
match self { match item {
Self::Text(s) => s.to_dl_arg(), TNArgument::Text(s) => s.into(),
Self::Null => NA, TNArgument::Null => NA,
} }
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Debug, Clone, PartialEq, Eq)]
pub enum Body { pub enum Body {
Text(String), Text(String),
Tags(Vec<Tag>), Tags(Vec<Tag>),
Null, Null,
} }
impl ToDaletlBody for Body { impl From<Body> for daletl::Body {
fn to_dl_body(self) -> daletl::Body { fn from(item: Body) -> daletl::Body {
match self { match item {
Body::Null => NB, Body::Null => NB,
Body::Tags(v) => v.to_dl_body(), Body::Tags(v) => v.into(),
Body::Text(v) => v.to_dl_body(), Body::Text(v) => v.into(),
} }
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Debug, Clone, PartialEq, Eq)]
pub enum Arg { pub enum Arg {
Text(String), Text(String),
Number(u8), Number(u8),
Null, Null,
} }
impl ToDaletlArgument for Arg { impl From<Arg> for daletl::Argument {
fn to_dl_arg(self) -> daletl::Argument { fn from(item: Arg) -> daletl::Argument {
match self { match item {
Arg::Null => NA, Arg::Null => NA,
Arg::Number(v) => v.to_dl_arg(), Arg::Number(v) => v.into(),
Arg::Text(v) => v.to_dl_arg(), Arg::Text(v) => v.into(),
} }
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Debug, Clone, PartialEq, Eq)]
/// Not null argument /// Not null argument
pub enum NNArg { pub enum NNArg {
Text(String), Text(String),
Number(u8), Number(u8),
} }
impl ToDaletlArgument for NNArg { impl From<NNArg> for daletl::Argument {
fn to_dl_arg(self) -> daletl::Argument { fn from(item: NNArg) -> daletl::Argument {
match self { match item {
NNArg::Number(v) => v.to_dl_arg(), NNArg::Number(v) => v.into(),
NNArg::Text(v) => v.to_dl_arg(), NNArg::Text(v) => v.into(),
} }
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(AutoFrom, Debug, Clone, PartialEq, Eq)]
pub enum NNBody { pub enum NNBody {
Text(String), Text(String),
Tags(Vec<Tag>), Tags(Vec<Tag>),
} }
impl ToDaletlBody for NNBody { impl From<NNBody> for daletl::Body {
fn to_dl_body(self) -> daletl::Body { fn from(item: NNBody) -> daletl::Body {
match self { match item {
NNBody::Text(v) => v.to_dl_body(), NNBody::Text(v) => v.into(),
NNBody::Tags(v) => v.to_dl_body(), NNBody::Tags(v) => v.into(),
} }
} }
} }
impl ToDaletlBody for Vec<Tag> { impl From<Vec<Tag>> for daletl::Body {
fn to_dl_body(self) -> daletl::Body { fn from(item: Vec<Tag>) -> daletl::Body {
daletl::Body::Tags(self.to_dl()) daletl::Body::Tags(item.into_iter().map(|tag| tag.into()).collect())
} }
} }
impl ToDaletl for Vec<Tag> { impl ToDaletlRoot for Root {
fn to_dl(self) -> Vec<daletl::Tag> { fn to_dl_root(self) -> daletl::Root {
self.into_iter().map(|tag| tag.to_dl_tag()).collect() self.into_iter().map(|tag| tag.into()).collect()
}
}
impl ToDaletlBody for String {
fn to_dl_body(self) -> daletl::Body {
daletl::Body::Text(self)
}
}
impl ToDaletlArgument for String {
fn to_dl_arg(self) -> daletl::Argument {
daletl::Argument::Text(self)
}
}
impl ToDaletlArgument for u8 {
fn to_dl_arg(self) -> daletl::Argument {
daletl::Argument::Number(self)
} }
} }

View file

@ -1,7 +1,10 @@
use dalet::{ use dalet::{
daletl::ToDaletl, daletl::ToDaletlRoot,
daletpack::*, daletpack::*,
typed::{Body, Hl, NNBody, TNArgument, Tag}, typed::{
Body, Hl, NNBody, Root, TNArgument,
Tag::{self, *},
},
}; };
use flate2::Compression; use flate2::Compression;
use std::io::Write; use std::io::Write;
@ -32,55 +35,53 @@ pub fn compress_zlib(data: &Vec<u8>) -> std::io::Result<Vec<u8>> {
#[test] #[test]
fn bench() { fn bench() {
let page: Vec<Tag> = vec![ let page: Root = vec![
Tag::H("I am heading".to_owned(), Hl::One), H("I am heading".into(), Hl::One),
Tag::H("Heading 2".to_owned(), Hl::Two), H("Heading 2".into(), Hl::Two),
Tag::El(NNBody::Tags(vec![ El(vec![
Tag::El(NNBody::Text("Some ".to_owned())), El("Some ".into()),
Tag::B("bold".to_owned()), B("bold".into()),
Tag::I("italic".to_owned()), I("italic".into()),
Tag::S("strike".to_owned()), S("strike".into()),
])), ]
Tag::Br, .into()),
Tag::Code("Hello world".to_owned(), TNArgument::Null), Br,
Tag::Br, Code("Hello world".into(), TNArgument::Null),
Tag::Ul(vec![ Br,
Tag::El(NNBody::Text("abc".to_owned())), Ul(vec![
Tag::El(NNBody::Tags(vec![ El("abc".into()),
Tag::El(NNBody::Text("def".to_owned())), El(vec![
Tag::Ul(vec![ El("def".into()),
Tag::El(NNBody::Text("defabc".to_owned())), Ul(vec![El("defabc".into()), El("defdef".into())]),
Tag::El(NNBody::Text("defdef".to_owned())), ]
.into()),
El("xyz".into()),
]), ]),
])), Br,
Tag::El(NNBody::Text("xyz".to_owned())), El(vec![
]), El("Lorem ipsum ".into()),
Tag::Br, Link(
Tag::El(NNBody::Tags(vec![ vec![Img("https://my-picture".into())].into(),
Tag::El(NNBody::Text("Lorem ipsum ".to_owned())), "https://some-link".into(),
Tag::Link(
Body::Tags(vec![Tag::Img("https://my-picture".to_owned())]),
"https://some-link".to_owned(),
), ),
Tag::El(NNBody::Text( El(" dolor sit amet consequetur adipiscing elit".into()),
" dolor sit amet consequetur adipiscing elit".to_owned(), ]
)), .into()),
])), Table(vec![
Tag::Table(vec![ Tpcol(vec![
Tag::Tpcol(vec![ El("Col 1".into()),
Tag::El(NNBody::Text("Col 1".to_owned())), El("Col 2".into()),
Tag::El(NNBody::Text("Col 2".to_owned())), El("Col 3".into()),
Tag::El(NNBody::Text("Col 3".to_owned())),
]), ]),
Tag::Tcol(vec![ Tcol(vec![
Tag::El(NNBody::Text("Never gonna".to_owned())), El("Never gonna".into()),
Tag::El(NNBody::Text("give you".to_owned())), El("give you".into()),
Tag::El(NNBody::Text("up".to_owned())), El("up".into()),
]), ]),
]), ]),
]; ];
let dalet_page = page.to_dl(); let dalet_page = page.to_dl_root();
let markdown = iprint!("Markdown", include_str!("./bench.md").as_bytes().to_vec()); let markdown = iprint!("Markdown", include_str!("./bench.md").as_bytes().to_vec());
let daletpack = iprint!("Daletpack", encode_no_compress(&dalet_page).unwrap()); let daletpack = iprint!("Daletpack", encode_no_compress(&dalet_page).unwrap());