mirror of
https://github.com/TxtDot/dalet-rs.git
synced 2025-03-13 11:14:37 +03:00
This commit is contained in:
parent
5eb9e2abb6
commit
2737a066f5
14 changed files with 1202 additions and 21 deletions
257
src/abstractions.rs
Normal file
257
src/abstractions.rs
Normal file
|
@ -0,0 +1,257 @@
|
|||
use num_enum::TryFromPrimitive;
|
||||
|
||||
use crate::daletl::{self, t_new, Tid};
|
||||
|
||||
const NB: daletl::Body = daletl::Body::Null;
|
||||
const NA: daletl::Argument = daletl::Argument::Null;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Tag {
|
||||
El(NotNullBody),
|
||||
H(String, HeadingLevel),
|
||||
P(NotNullBody),
|
||||
Br,
|
||||
Ul(Vec<Tag>),
|
||||
Ol(Vec<Tag>),
|
||||
Row(Vec<Tag>, AlignArgument),
|
||||
Link(Body, String),
|
||||
Navlink(Body, String),
|
||||
Btn(Body, String),
|
||||
Navbtn(Body, String),
|
||||
Img(String),
|
||||
Table(Vec<Tag>),
|
||||
Tcol(Vec<Tag>),
|
||||
Tpcol(Vec<Tag>),
|
||||
Hr,
|
||||
B(String),
|
||||
I(String),
|
||||
Bq(NotNullBody),
|
||||
Footlnk(TextOrNumberArgument),
|
||||
Footn(String, TextOrNumberArgument),
|
||||
A(TextOrNumberArgument),
|
||||
S(String),
|
||||
Sup(String),
|
||||
Sub(String),
|
||||
Disc(NotNullBody),
|
||||
Bl(NotNullBody, AlignArgument),
|
||||
Carousel(Vec<Tag>),
|
||||
Code(String, TextOrNullArgument),
|
||||
}
|
||||
|
||||
pub trait ToDaletl {
|
||||
fn to_daletl(self) -> Vec<daletl::Tag>;
|
||||
}
|
||||
|
||||
pub trait ToDaletlTag {
|
||||
fn to_daletl_tag(self) -> daletl::Tag;
|
||||
}
|
||||
|
||||
impl ToDaletlTag for Tag {
|
||||
fn to_daletl_tag(self) -> daletl::Tag {
|
||||
match self {
|
||||
Tag::El(b) => t_new(Tid::El, b.to_daletl_body(), NA),
|
||||
Tag::H(b, a) => t_new(Tid::H, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::P(b) => t_new(Tid::P, b.to_daletl_body(), NA),
|
||||
Tag::Br => t_new(Tid::Br, NB, NA),
|
||||
Tag::Ul(b) => t_new(Tid::Ul, b.to_daletl_body(), NA),
|
||||
Tag::Ol(b) => t_new(Tid::Ol, b.to_daletl_body(), NA),
|
||||
Tag::Row(b, a) => t_new(Tid::Row, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::Link(b, a) => t_new(Tid::Link, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::Navlink(b, a) => t_new(Tid::Navlink, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::Btn(b, a) => t_new(Tid::Btn, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::Navbtn(b, a) => t_new(Tid::Navbtn, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::Img(a) => t_new(Tid::Img, NB, a.to_daletl_argument()),
|
||||
Tag::Table(b) => t_new(Tid::Table, b.to_daletl_body(), NA),
|
||||
Tag::Tcol(b) => t_new(Tid::Tcol, b.to_daletl_body(), NA),
|
||||
Tag::Tpcol(b) => t_new(Tid::Tpcol, b.to_daletl_body(), NA),
|
||||
Tag::Hr => t_new(Tid::Hr, NB, NA),
|
||||
Tag::B(b) => t_new(Tid::B, b.to_daletl_body(), NA),
|
||||
Tag::I(b) => t_new(Tid::I, b.to_daletl_body(), NA),
|
||||
Tag::Bq(b) => t_new(Tid::Bq, b.to_daletl_body(), NA),
|
||||
Tag::Footlnk(a) => t_new(Tid::Footlnk, NB, a.to_daletl_argument()),
|
||||
Tag::Footn(b, a) => t_new(Tid::Footn, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::A(a) => t_new(Tid::A, NB, a.to_daletl_argument()),
|
||||
Tag::S(b) => t_new(Tid::S, b.to_daletl_body(), NA),
|
||||
Tag::Sup(b) => t_new(Tid::Sup, b.to_daletl_body(), NA),
|
||||
Tag::Sub(b) => t_new(Tid::Sub, b.to_daletl_body(), NA),
|
||||
Tag::Disc(b) => t_new(Tid::Disc, b.to_daletl_body(), NA),
|
||||
Tag::Bl(b, a) => t_new(Tid::Bl, b.to_daletl_body(), a.to_daletl_argument()),
|
||||
Tag::Carousel(b) => t_new(Tid::Carousel, b.to_daletl_body(), NA),
|
||||
Tag::Code(s, a) => t_new(Tid::Code, s.to_daletl_body(), a.to_daletl_argument()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToDaletlBody {
|
||||
fn to_daletl_body(self) -> daletl::Body;
|
||||
}
|
||||
|
||||
pub trait ToDaletlArgument {
|
||||
fn to_daletl_argument(self) -> daletl::Argument;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum HeadingLevel {
|
||||
One = 1,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for HeadingLevel {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
match self {
|
||||
HeadingLevel::One => NA,
|
||||
HeadingLevel::Two => 2u8.to_daletl_argument(),
|
||||
HeadingLevel::Three => 3u8.to_daletl_argument(),
|
||||
HeadingLevel::Four => 4u8.to_daletl_argument(),
|
||||
HeadingLevel::Five => 5u8.to_daletl_argument(),
|
||||
HeadingLevel::Six => 6u8.to_daletl_argument(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum AlignArgument {
|
||||
Start,
|
||||
Center,
|
||||
End,
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for AlignArgument {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
match self {
|
||||
Self::Start => NA,
|
||||
Self::Center => 1u8.to_daletl_argument(),
|
||||
Self::End => 2u8.to_daletl_argument(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TextOrNumberArgument {
|
||||
Text(String),
|
||||
Number(u8),
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for TextOrNumberArgument {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
match self {
|
||||
Self::Number(n) => n.to_daletl_argument(),
|
||||
Self::Text(s) => s.to_daletl_argument(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TextOrNullArgument {
|
||||
Text(String),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for TextOrNullArgument {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
match self {
|
||||
Self::Text(s) => s.to_daletl_argument(),
|
||||
Self::Null => NA,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Body {
|
||||
Text(String),
|
||||
Tags(Vec<Tag>),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl ToDaletlBody for Body {
|
||||
fn to_daletl_body(self) -> daletl::Body {
|
||||
match self {
|
||||
Body::Null => NB,
|
||||
Body::Tags(v) => v.to_daletl_body(),
|
||||
Body::Text(v) => v.to_daletl_body(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Argument {
|
||||
Text(String),
|
||||
Number(u8),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for Argument {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
match self {
|
||||
Argument::Null => NA,
|
||||
Argument::Number(v) => v.to_daletl_argument(),
|
||||
Argument::Text(v) => v.to_daletl_argument(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum NotNullArgument {
|
||||
Text(String),
|
||||
Number(u8),
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for NotNullArgument {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
match self {
|
||||
NotNullArgument::Number(v) => v.to_daletl_argument(),
|
||||
NotNullArgument::Text(v) => v.to_daletl_argument(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum NotNullBody {
|
||||
Text(String),
|
||||
Tags(Vec<Tag>),
|
||||
}
|
||||
|
||||
impl ToDaletlBody for NotNullBody {
|
||||
fn to_daletl_body(self) -> daletl::Body {
|
||||
match self {
|
||||
NotNullBody::Text(v) => v.to_daletl_body(),
|
||||
NotNullBody::Tags(v) => v.to_daletl_body(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDaletlBody for Vec<Tag> {
|
||||
fn to_daletl_body(self) -> daletl::Body {
|
||||
daletl::Body::Tags(self.to_daletl())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDaletl for Vec<Tag> {
|
||||
fn to_daletl(self) -> Vec<daletl::Tag> {
|
||||
self.into_iter().map(|tag| tag.to_daletl_tag()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDaletlBody for String {
|
||||
fn to_daletl_body(self) -> daletl::Body {
|
||||
daletl::Body::Text(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for String {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
daletl::Argument::Text(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDaletlArgument for u8 {
|
||||
fn to_daletl_argument(self) -> daletl::Argument {
|
||||
daletl::Argument::Number(self)
|
||||
}
|
||||
}
|
13
src/commands.rs
Normal file
13
src/commands.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "cimengine", bin_name = "cimengine")]
|
||||
#[command(about = "CIMEngine build tools")]
|
||||
pub struct Cli {
|
||||
#[command(subcommand)]
|
||||
pub cmd: Commands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
#[clap(author, version, about)]
|
||||
pub enum Commands {}
|
95
src/daletl.rs
Normal file
95
src/daletl.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Tag {
|
||||
pub id: Tid,
|
||||
pub body: Body,
|
||||
pub argument: Argument,
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
#[inline]
|
||||
pub fn new(id: Tid, body: Body, argument: Argument) -> Tag {
|
||||
Tag { id, body, argument }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn t_new(id: Tid, body: Body, argument: Argument) -> Tag {
|
||||
Tag::new(id, body, argument)
|
||||
}
|
||||
|
||||
pub trait IsNull {
|
||||
fn is_null(&self) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(untagged)]
|
||||
pub enum Body {
|
||||
Text(String),
|
||||
Tags(Vec<Tag>),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl IsNull for Body {
|
||||
fn is_null(&self) -> bool {
|
||||
match self {
|
||||
Self::Null => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(untagged)]
|
||||
pub enum Argument {
|
||||
Text(String),
|
||||
Number(u8),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl IsNull for Argument {
|
||||
fn is_null(&self) -> bool {
|
||||
match self {
|
||||
Self::Null => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, PartialEq, Eq, TryFromPrimitive, Copy)]
|
||||
#[repr(u8)]
|
||||
/// Tag Id
|
||||
pub enum Tid {
|
||||
El,
|
||||
H,
|
||||
P,
|
||||
Br,
|
||||
Ul,
|
||||
Ol,
|
||||
Row,
|
||||
Link,
|
||||
Navlink,
|
||||
Btn,
|
||||
Navbtn,
|
||||
Img,
|
||||
Table,
|
||||
Tcol,
|
||||
Tpcol,
|
||||
Hr,
|
||||
B,
|
||||
I,
|
||||
Bq,
|
||||
Footlnk,
|
||||
Footn,
|
||||
A,
|
||||
S,
|
||||
Sup,
|
||||
Sub,
|
||||
Disc,
|
||||
Bl,
|
||||
Carousel,
|
||||
Code,
|
||||
}
|
110
src/daletpack/encode.rs
Normal file
110
src/daletpack/encode.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
use crate::daletl::{Argument, Body, IsNull, Tag, Tid};
|
||||
|
||||
use super::{DaletPackError, TypeId};
|
||||
|
||||
pub fn encode(root: &Vec<Tag>) -> Result<Vec<u8>, DaletPackError> {
|
||||
Ok(zstd::bulk::compress(&encode_no_compress(root)?, 5)
|
||||
.map_err(|_| DaletPackError::ZstdCompressError)?)
|
||||
}
|
||||
|
||||
pub fn encode_no_compress(root: &Vec<Tag>) -> Result<Vec<u8>, DaletPackError> {
|
||||
if root.len() > 2usize.pow(32) {
|
||||
return Err(DaletPackError::RootMaxSizeExceeded);
|
||||
}
|
||||
|
||||
let mut bv: Vec<u8> = Vec::new();
|
||||
|
||||
for tag in root {
|
||||
write_tag(&mut bv, tag)?;
|
||||
}
|
||||
|
||||
Ok(bv)
|
||||
}
|
||||
|
||||
fn write_int(bv: &mut Vec<u8>, n: u8) {
|
||||
bv.push(1);
|
||||
bv.push(n);
|
||||
}
|
||||
|
||||
fn write_str(bv: &mut Vec<u8>, string: &String) -> Result<(), DaletPackError> {
|
||||
let size = string.len();
|
||||
|
||||
if size > 2usize.pow(32) {
|
||||
return Err(DaletPackError::StrMaxSizeExceeded);
|
||||
}
|
||||
|
||||
if size <= 256 {
|
||||
bv.push(TypeId::Str8 as u8);
|
||||
bv.push((size - 1) as u8);
|
||||
} else if size <= 65536 {
|
||||
bv.push(TypeId::Str16 as u8);
|
||||
bv.extend(((size - 1) as u16).to_be_bytes());
|
||||
} else {
|
||||
bv.push(TypeId::Str32 as u8);
|
||||
bv.extend(((size - 1) as u32).to_be_bytes());
|
||||
}
|
||||
|
||||
bv.extend_from_slice(string.as_bytes());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_array(bv: &mut Vec<u8>, arr: &Vec<Tag>) -> Result<(), DaletPackError> {
|
||||
if arr.len() > 2usize.pow(32) {
|
||||
return Err(DaletPackError::ArrMaxSizeExceeded);
|
||||
}
|
||||
|
||||
bv.push(TypeId::TagArray as u8);
|
||||
|
||||
for tag in arr {
|
||||
write_tag(bv, tag)?;
|
||||
}
|
||||
|
||||
bv.push(TypeId::TagArrayEnd as u8);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tag(bv: &mut Vec<u8>, tag: &Tag) -> Result<(), DaletPackError> {
|
||||
if tag.id == Tid::El {
|
||||
write_tag_body(bv, &tag.body)?;
|
||||
} else if tag.body.is_null() && tag.argument.is_null() {
|
||||
bv.push(TypeId::TagId as u8);
|
||||
bv.push(tag.id as u8);
|
||||
} else if tag.argument.is_null() {
|
||||
bv.push(TypeId::TagIdBody as u8);
|
||||
bv.push(tag.id as u8);
|
||||
write_tag_body(bv, &tag.body)?;
|
||||
} else if tag.body.is_null() {
|
||||
bv.push(TypeId::TagIdArgument as u8);
|
||||
bv.push(tag.id as u8);
|
||||
write_tag_argument(bv, &tag.argument)?;
|
||||
} else {
|
||||
bv.push(TypeId::TagIdBodyArgument as u8);
|
||||
bv.push(tag.id as u8);
|
||||
write_tag_body(bv, &tag.body)?;
|
||||
write_tag_argument(bv, &tag.argument)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tag_body(bv: &mut Vec<u8>, body: &Body) -> Result<(), DaletPackError> {
|
||||
match body {
|
||||
Body::Text(s) => write_str(bv, s)?,
|
||||
Body::Tags(tags) => write_array(bv, tags)?,
|
||||
Body::Null => Err(DaletPackError::WriteNullBody)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tag_argument(bv: &mut Vec<u8>, argument: &Argument) -> Result<(), DaletPackError> {
|
||||
match argument {
|
||||
Argument::Text(s) => write_str(bv, s)?,
|
||||
Argument::Number(n) => write_int(bv, *n),
|
||||
Argument::Null => Err(DaletPackError::WriteNullArgument)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
6
src/daletpack/mod.rs
Normal file
6
src/daletpack/mod.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
mod encode;
|
||||
mod types;
|
||||
|
||||
pub mod utils;
|
||||
pub use encode::*;
|
||||
pub use types::*;
|
27
src/daletpack/types.rs
Normal file
27
src/daletpack/types.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use num_enum::TryFromPrimitive;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum DaletPackError {
|
||||
StrMaxSizeExceeded,
|
||||
ArrMaxSizeExceeded,
|
||||
RootMaxSizeExceeded,
|
||||
ZstdCompressError,
|
||||
|
||||
WriteNullBody,
|
||||
WriteNullArgument,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, TryFromPrimitive, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum TypeId {
|
||||
Int8 = 1,
|
||||
Str8 = 4,
|
||||
Str16,
|
||||
Str32,
|
||||
TagArray,
|
||||
TagArrayEnd,
|
||||
TagId = 12,
|
||||
TagIdBody,
|
||||
TagIdArgument,
|
||||
TagIdBodyArgument,
|
||||
}
|
3
src/daletpack/utils.rs
Normal file
3
src/daletpack/utils.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub fn compress_zstd(data: &Vec<u8>) -> std::io::Result<Vec<u8>> {
|
||||
zstd::bulk::compress(data, 22)
|
||||
}
|
8
src/lib.rs
Normal file
8
src/lib.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#[cfg(feature = "types")]
|
||||
pub mod daletl;
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
pub mod abstractions;
|
||||
|
||||
#[cfg(feature = "daletpack")]
|
||||
pub mod daletpack;
|
3
src/main.rs
Normal file
3
src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod commands;
|
||||
|
||||
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue