From 5058bb812be425a05e708019750d0581603448c2 Mon Sep 17 00:00:00 2001 From: Artemy Egorov Date: Sat, 3 Aug 2024 12:47:33 +0300 Subject: [PATCH] feat: AutoFrom --- Cargo.lock | 11 +++ Cargo.toml | 1 + src/daletl.rs | 27 ++------ src/typed.rs | 185 +++++++++++++++++++++++-------------------------- tests/bench.rs | 89 ++++++++++++------------ 5 files changed, 149 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b6f371..29e874b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,6 +196,7 @@ dependencies = [ "bincode", "chumsky", "clap", + "enum-procs", "flate2", "num_enum", "rmp-serde", @@ -204,6 +205,16 @@ dependencies = [ "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]] name = "equivalent" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 9ee130a..d55c241 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ serde = { version = "1.0", features = ["derive"] } serde_repr = "0.1" zstd = "0.13.2" chumsky = { version = "=1.0.0-alpha.7", features = ["label"], optional = true } +enum-procs = "0.3.0" [dev-dependencies] rmp-serde = { version = "1.3.0" } diff --git a/src/daletl.rs b/src/daletl.rs index 7951b60..b95d07a 100644 --- a/src/daletl.rs +++ b/src/daletl.rs @@ -1,7 +1,9 @@ +use enum_procs::AutoFrom; +use num_enum::TryFromPrimitive; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use num_enum::TryFromPrimitive; +pub type Root = Vec; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct Tag { @@ -22,7 +24,7 @@ pub fn t_new(id: Tid, body: Body, argument: Argument) -> Tag { Tag::new(id, body, argument) } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[serde(untagged)] pub enum Body { Text(String), @@ -30,7 +32,7 @@ pub enum Body { Null, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[serde(untagged)] pub enum Argument { Text(String), @@ -96,22 +98,7 @@ pub trait IsNull { fn is_null(&self) -> bool; } -pub trait ToDaletl { +pub trait ToDaletlRoot { /// Convert to daletl root - fn to_dl(self) -> Vec; -} - -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; + fn to_dl_root(self) -> Root; } diff --git a/src/typed.rs b/src/typed.rs index cfa2a9d..1fb150d 100644 --- a/src/typed.rs +++ b/src/typed.rs @@ -1,10 +1,13 @@ +use enum_procs::AutoFrom; 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 NA: daletl::Argument = daletl::Argument::Null; +pub type Root = Vec; + #[derive(Debug, Clone, PartialEq, Eq)] pub enum Tag { El(NNBody), @@ -39,39 +42,39 @@ pub enum Tag { Pre(String), } -impl ToDaletlTag for Tag { - fn to_dl_tag(self) -> daletl::Tag { - match self { - Tag::El(b) => t_new(Tid::El, b.to_dl_body(), NA), - Tag::H(b, a) => t_new(Tid::H, b.to_dl_body(), a.to_dl_arg()), - Tag::P(b) => t_new(Tid::P, b.to_dl_body(), NA), +impl From for daletl::Tag { + fn from(item: Tag) -> daletl::Tag { + match item { + Tag::El(b) => t_new(Tid::El, b.into(), NA), + Tag::H(b, a) => t_new(Tid::H, b.into(), a.into()), + Tag::P(b) => t_new(Tid::P, b.into(), NA), Tag::Br => t_new(Tid::Br, NB, NA), - Tag::Ul(b) => t_new(Tid::Ul, b.to_dl_body(), NA), - Tag::Ol(b) => t_new(Tid::Ol, b.to_dl_body(), NA), - Tag::Row(b, a) => t_new(Tid::Row, b.to_dl_body(), a.to_dl_arg()), - Tag::Link(b, a) => t_new(Tid::Link, b.to_dl_body(), a.to_dl_arg()), - Tag::Navlink(b, a) => t_new(Tid::Navlink, b.to_dl_body(), a.to_dl_arg()), - Tag::Btn(b, a) => t_new(Tid::Btn, b.to_dl_body(), a.to_dl_arg()), - Tag::Navbtn(b, a) => t_new(Tid::Navbtn, b.to_dl_body(), a.to_dl_arg()), - Tag::Img(a) => t_new(Tid::Img, NB, a.to_dl_arg()), - Tag::Table(b) => t_new(Tid::Table, b.to_dl_body(), NA), - Tag::Tcol(b) => t_new(Tid::Tcol, b.to_dl_body(), NA), - Tag::Tpcol(b) => t_new(Tid::Tpcol, b.to_dl_body(), NA), + Tag::Ul(b) => t_new(Tid::Ul, b.into(), NA), + Tag::Ol(b) => t_new(Tid::Ol, b.into(), NA), + Tag::Row(b, a) => t_new(Tid::Row, b.into(), a.into()), + Tag::Link(b, a) => t_new(Tid::Link, b.into(), a.into()), + Tag::Navlink(b, a) => t_new(Tid::Navlink, b.into(), a.into()), + Tag::Btn(b, a) => t_new(Tid::Btn, b.into(), a.into()), + Tag::Navbtn(b, a) => t_new(Tid::Navbtn, b.into(), a.into()), + Tag::Img(a) => t_new(Tid::Img, NB, a.into()), + Tag::Table(b) => t_new(Tid::Table, b.into(), NA), + Tag::Tcol(b) => t_new(Tid::Tcol, b.into(), NA), + Tag::Tpcol(b) => t_new(Tid::Tpcol, b.into(), NA), Tag::Hr => t_new(Tid::Hr, NB, NA), - Tag::B(b) => t_new(Tid::B, b.to_dl_body(), NA), - Tag::I(b) => t_new(Tid::I, b.to_dl_body(), NA), - Tag::Bq(b) => t_new(Tid::Bq, b.to_dl_body(), NA), - Tag::Footlnk(a) => t_new(Tid::Footlnk, NB, a.to_dl_arg()), - Tag::Footn(b, a) => t_new(Tid::Footn, b.to_dl_body(), a.to_dl_arg()), - Tag::A(a) => t_new(Tid::A, NB, a.to_dl_arg()), - Tag::S(b) => t_new(Tid::S, b.to_dl_body(), NA), - Tag::Sup(b) => t_new(Tid::Sup, b.to_dl_body(), NA), - Tag::Sub(b) => t_new(Tid::Sub, b.to_dl_body(), NA), - Tag::Disc(b) => t_new(Tid::Disc, b.to_dl_body(), NA), - Tag::Bl(b, a) => t_new(Tid::Bl, b.to_dl_body(), a.to_dl_arg()), - Tag::Carousel(b) => t_new(Tid::Carousel, b.to_dl_body(), NA), - Tag::Code(s, a) => t_new(Tid::Code, s.to_dl_body(), a.to_dl_arg()), - Tag::Pre(s) => t_new(Tid::Pre, s.to_dl_body(), NA), + Tag::B(b) => t_new(Tid::B, b.into(), NA), + Tag::I(b) => t_new(Tid::I, b.into(), NA), + Tag::Bq(b) => t_new(Tid::Bq, b.into(), NA), + Tag::Footlnk(a) => t_new(Tid::Footlnk, NB, a.into()), + Tag::Footn(b, a) => t_new(Tid::Footn, b.into(), a.into()), + Tag::A(a) => t_new(Tid::A, NB, a.into()), + Tag::S(b) => t_new(Tid::S, b.into(), NA), + Tag::Sup(b) => t_new(Tid::Sup, b.into(), NA), + Tag::Sub(b) => t_new(Tid::Sub, b.into(), NA), + Tag::Disc(b) => t_new(Tid::Disc, b.into(), NA), + Tag::Bl(b, a) => t_new(Tid::Bl, b.into(), a.into()), + Tag::Carousel(b) => t_new(Tid::Carousel, b.into(), NA), + Tag::Code(s, a) => t_new(Tid::Code, s.into(), a.into()), + Tag::Pre(s) => t_new(Tid::Pre, s.into(), NA), } } } @@ -88,15 +91,15 @@ pub enum Hl { Six, } -impl ToDaletlArgument for Hl { - fn to_dl_arg(self) -> daletl::Argument { - match self { +impl From for daletl::Argument { + fn from(item: Hl) -> daletl::Argument { + match item { Hl::One => NA, - Hl::Two => 2u8.to_dl_arg(), - Hl::Three => 3u8.to_dl_arg(), - Hl::Four => 4u8.to_dl_arg(), - Hl::Five => 5u8.to_dl_arg(), - Hl::Six => 6u8.to_dl_arg(), + Hl::Two => 2u8.into(), + Hl::Three => 3u8.into(), + Hl::Four => 4u8.into(), + Hl::Five => 5u8.into(), + Hl::Six => 6u8.into(), } } } @@ -109,122 +112,104 @@ pub enum AlignArgument { End, } -impl ToDaletlArgument for AlignArgument { - fn to_dl_arg(self) -> daletl::Argument { - match self { - Self::Start => NA, - Self::Center => 1u8.to_dl_arg(), - Self::End => 2u8.to_dl_arg(), +impl From for daletl::Argument { + fn from(item: AlignArgument) -> daletl::Argument { + match item { + AlignArgument::Start => NA, + AlignArgument::Center => 1u8.into(), + AlignArgument::End => 2u8.into(), } } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Debug, Clone, PartialEq, Eq)] pub enum TNArgument { Text(String), Null, } -impl ToDaletlArgument for TNArgument { - fn to_dl_arg(self) -> daletl::Argument { - match self { - Self::Text(s) => s.to_dl_arg(), - Self::Null => NA, +impl From for daletl::Argument { + fn from(item: TNArgument) -> daletl::Argument { + match item { + TNArgument::Text(s) => s.into(), + TNArgument::Null => NA, } } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Debug, Clone, PartialEq, Eq)] pub enum Body { Text(String), Tags(Vec), Null, } -impl ToDaletlBody for Body { - fn to_dl_body(self) -> daletl::Body { - match self { +impl From for daletl::Body { + fn from(item: Body) -> daletl::Body { + match item { Body::Null => NB, - Body::Tags(v) => v.to_dl_body(), - Body::Text(v) => v.to_dl_body(), + Body::Tags(v) => v.into(), + Body::Text(v) => v.into(), } } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Debug, Clone, PartialEq, Eq)] pub enum Arg { Text(String), Number(u8), Null, } -impl ToDaletlArgument for Arg { - fn to_dl_arg(self) -> daletl::Argument { - match self { +impl From for daletl::Argument { + fn from(item: Arg) -> daletl::Argument { + match item { Arg::Null => NA, - Arg::Number(v) => v.to_dl_arg(), - Arg::Text(v) => v.to_dl_arg(), + Arg::Number(v) => v.into(), + Arg::Text(v) => v.into(), } } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Debug, Clone, PartialEq, Eq)] /// Not null argument pub enum NNArg { Text(String), Number(u8), } -impl ToDaletlArgument for NNArg { - fn to_dl_arg(self) -> daletl::Argument { - match self { - NNArg::Number(v) => v.to_dl_arg(), - NNArg::Text(v) => v.to_dl_arg(), +impl From for daletl::Argument { + fn from(item: NNArg) -> daletl::Argument { + match item { + NNArg::Number(v) => v.into(), + NNArg::Text(v) => v.into(), } } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(AutoFrom, Debug, Clone, PartialEq, Eq)] pub enum NNBody { Text(String), Tags(Vec), } -impl ToDaletlBody for NNBody { - fn to_dl_body(self) -> daletl::Body { - match self { - NNBody::Text(v) => v.to_dl_body(), - NNBody::Tags(v) => v.to_dl_body(), +impl From for daletl::Body { + fn from(item: NNBody) -> daletl::Body { + match item { + NNBody::Text(v) => v.into(), + NNBody::Tags(v) => v.into(), } } } -impl ToDaletlBody for Vec { - fn to_dl_body(self) -> daletl::Body { - daletl::Body::Tags(self.to_dl()) +impl From> for daletl::Body { + fn from(item: Vec) -> daletl::Body { + daletl::Body::Tags(item.into_iter().map(|tag| tag.into()).collect()) } } -impl ToDaletl for Vec { - fn to_dl(self) -> Vec { - self.into_iter().map(|tag| tag.to_dl_tag()).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) +impl ToDaletlRoot for Root { + fn to_dl_root(self) -> daletl::Root { + self.into_iter().map(|tag| tag.into()).collect() } } diff --git a/tests/bench.rs b/tests/bench.rs index 343ac98..5f10d41 100644 --- a/tests/bench.rs +++ b/tests/bench.rs @@ -1,7 +1,10 @@ use dalet::{ - daletl::ToDaletl, + daletl::ToDaletlRoot, daletpack::*, - typed::{Body, Hl, NNBody, TNArgument, Tag}, + typed::{ + Body, Hl, NNBody, Root, TNArgument, + Tag::{self, *}, + }, }; use flate2::Compression; use std::io::Write; @@ -32,55 +35,53 @@ pub fn compress_zlib(data: &Vec) -> std::io::Result> { #[test] fn bench() { - let page: Vec = vec![ - Tag::H("I am heading".to_owned(), Hl::One), - Tag::H("Heading 2".to_owned(), Hl::Two), - Tag::El(NNBody::Tags(vec![ - Tag::El(NNBody::Text("Some ".to_owned())), - Tag::B("bold".to_owned()), - Tag::I("italic".to_owned()), - Tag::S("strike".to_owned()), - ])), - Tag::Br, - Tag::Code("Hello world".to_owned(), TNArgument::Null), - Tag::Br, - Tag::Ul(vec![ - Tag::El(NNBody::Text("abc".to_owned())), - Tag::El(NNBody::Tags(vec![ - Tag::El(NNBody::Text("def".to_owned())), - Tag::Ul(vec![ - Tag::El(NNBody::Text("defabc".to_owned())), - Tag::El(NNBody::Text("defdef".to_owned())), - ]), - ])), - Tag::El(NNBody::Text("xyz".to_owned())), + let page: Root = vec![ + H("I am heading".into(), Hl::One), + H("Heading 2".into(), Hl::Two), + El(vec![ + El("Some ".into()), + B("bold".into()), + I("italic".into()), + S("strike".into()), + ] + .into()), + Br, + Code("Hello world".into(), TNArgument::Null), + Br, + Ul(vec![ + El("abc".into()), + El(vec![ + El("def".into()), + Ul(vec![El("defabc".into()), El("defdef".into())]), + ] + .into()), + El("xyz".into()), ]), - Tag::Br, - Tag::El(NNBody::Tags(vec![ - Tag::El(NNBody::Text("Lorem ipsum ".to_owned())), - Tag::Link( - Body::Tags(vec![Tag::Img("https://my-picture".to_owned())]), - "https://some-link".to_owned(), + Br, + El(vec![ + El("Lorem ipsum ".into()), + Link( + vec![Img("https://my-picture".into())].into(), + "https://some-link".into(), ), - Tag::El(NNBody::Text( - " dolor sit amet consequetur adipiscing elit".to_owned(), - )), - ])), - Tag::Table(vec![ - Tag::Tpcol(vec![ - Tag::El(NNBody::Text("Col 1".to_owned())), - Tag::El(NNBody::Text("Col 2".to_owned())), - Tag::El(NNBody::Text("Col 3".to_owned())), + El(" dolor sit amet consequetur adipiscing elit".into()), + ] + .into()), + Table(vec![ + Tpcol(vec![ + El("Col 1".into()), + El("Col 2".into()), + El("Col 3".into()), ]), - Tag::Tcol(vec![ - Tag::El(NNBody::Text("Never gonna".to_owned())), - Tag::El(NNBody::Text("give you".to_owned())), - Tag::El(NNBody::Text("up".to_owned())), + Tcol(vec![ + El("Never gonna".into()), + El("give you".into()), + 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 daletpack = iprint!("Daletpack", encode_no_compress(&dalet_page).unwrap());