refactor(serde): use serde derive macro

This commit is contained in:
PoiScript 2019-06-27 16:59:59 +08:00
parent c86fef91a0
commit bd1fc756bd
22 changed files with 203 additions and 422 deletions

View file

@ -14,7 +14,7 @@ travis-ci = { repository = "PoiScript/orgize" }
[features] [features]
default = ["serde", "chrono"] default = ["serde", "chrono"]
extra-serde-info = [] extra-serde-info = ["serde"]
[dependencies] [dependencies]
bytecount = "0.5.1" bytecount = "0.5.1"
@ -22,7 +22,7 @@ chrono = { version = "0.4.7", optional = true }
indextree = "3.2.0" indextree = "3.2.0"
jetscii = "0.4.4" jetscii = "0.4.4"
memchr = "2.2.0" memchr = "2.2.0"
serde = { version = "1.0.93", optional = true } serde = { version = "1.0.93", optional = true, features = ["derive"] }
[dev-dependencies] [dev-dependencies]
pretty_assertions = "0.6.1" pretty_assertions = "0.6.1"

View file

@ -1,9 +1,11 @@
use memchr::{memchr, memchr_iter}; use memchr::{memchr, memchr_iter};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Block<'a> { pub struct Block<'a> {
pub name: &'a str, pub name: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub args: Option<&'a str>, pub args: Option<&'a str>,
} }

View file

@ -5,20 +5,25 @@ use memchr::memchr;
/// ///
/// there are two types of clock: *closed* clock and *running* clock. /// there are two types of clock: *closed* clock and *running* clock.
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub enum Clock<'a> { pub enum Clock<'a> {
/// closed Clock /// closed Clock
Closed { Closed {
start: Datetime<'a>, start: Datetime<'a>,
end: Datetime<'a>, end: Datetime<'a>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
repeater: Option<&'a str>, repeater: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
delay: Option<&'a str>, delay: Option<&'a str>,
duration: &'a str, duration: &'a str,
}, },
/// running Clock /// running Clock
Running { Running {
start: Datetime<'a>, start: Datetime<'a>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
repeater: Option<&'a str>, repeater: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
delay: Option<&'a str>, delay: Option<&'a str>,
}, },
} }

View file

@ -1,6 +1,7 @@
use memchr::{memchr, memchr2}; use memchr::{memchr, memchr2};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub enum Cookie<'a> { pub enum Cookie<'a> {
Percent(&'a str), Percent(&'a str),

View file

@ -1,6 +1,7 @@
use memchr::memchr_iter; use memchr::memchr_iter;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Drawer<'a> { pub struct Drawer<'a> {
pub name: &'a str, pub name: &'a str,

View file

@ -1,9 +1,11 @@
use memchr::{memchr, memchr_iter}; use memchr::{memchr, memchr_iter};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct DynBlock<'a> { pub struct DynBlock<'a> {
pub block_name: &'a str, pub block_name: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub arguments: Option<&'a str>, pub arguments: Option<&'a str>,
} }

View file

@ -1,6 +1,7 @@
use memchr::memchr; use memchr::memchr;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct FnDef<'a> { pub struct FnDef<'a> {
pub label: &'a str, pub label: &'a str,

View file

@ -1,9 +1,12 @@
use memchr::{memchr2, memchr2_iter}; use memchr::{memchr2, memchr2_iter};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct FnRef<'a> { pub struct FnRef<'a> {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub label: Option<&'a str>, pub label: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub definition: Option<&'a str>, pub definition: Option<&'a str>,
} }

View file

@ -7,17 +7,21 @@ pub const DEFAULT_TODO_KEYWORDS: &[&str] =
&["TODO", "DONE", "NEXT", "WAITING", "LATER", "CANCELLED"]; &["TODO", "DONE", "NEXT", "WAITING", "LATER", "CANCELLED"];
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Headline<'a> { pub struct Headline<'a> {
/// headline level, number of stars /// headline level, number of stars
pub level: usize, pub level: usize,
/// priority cookie /// priority cookie
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub priority: Option<char>, pub priority: Option<char>,
/// headline tags, including the sparated colons /// headline tags, including the sparated colons
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
pub tags: Vec<&'a str>, pub tags: Vec<&'a str>,
/// headline title /// headline title
pub title: &'a str, pub title: &'a str,
/// headline keyword /// headline keyword
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub keyword: Option<&'a str>, pub keyword: Option<&'a str>,
} }

View file

@ -1,11 +1,14 @@
use memchr::{memchr, memchr2}; use memchr::{memchr, memchr2};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct InlineCall<'a> { pub struct InlineCall<'a> {
pub name: &'a str, pub name: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub inside_header: Option<&'a str>, pub inside_header: Option<&'a str>,
pub args: &'a str, pub args: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub end_header: Option<&'a str>, pub end_header: Option<&'a str>,
} }

View file

@ -1,9 +1,11 @@
use memchr::{memchr, memchr2}; use memchr::{memchr, memchr2};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct InlineSrc<'a> { pub struct InlineSrc<'a> {
pub lang: &'a str, pub lang: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub option: Option<&'a str>, pub option: Option<&'a str>,
pub body: &'a str, pub body: &'a str,
} }

View file

@ -1,13 +1,17 @@
use memchr::{memchr, memchr2}; use memchr::{memchr, memchr2};
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Keyword<'a> { pub struct Keyword<'a> {
pub key: &'a str, pub key: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub option: Option<&'a str>, pub option: Option<&'a str>,
pub value: &'a str, pub value: &'a str,
} }
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct BabelCall<'a> { pub struct BabelCall<'a> {
pub key: &'a str, pub key: &'a str,

View file

@ -2,9 +2,11 @@ use jetscii::Substring;
use memchr::memchr; use memchr::memchr;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Link<'a> { pub struct Link<'a> {
pub path: &'a str, pub path: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub desc: Option<&'a str>, pub desc: Option<&'a str>,
} }

View file

@ -2,6 +2,7 @@ use memchr::memchr_iter;
use std::iter::once; use std::iter::once;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct List { pub struct List {
pub indent: usize, pub indent: usize,
@ -61,6 +62,7 @@ impl List {
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct ListItem<'a> { pub struct ListItem<'a> {
pub bullet: &'a str, pub bullet: &'a str,

View file

@ -2,9 +2,11 @@ use jetscii::Substring;
use memchr::memchr2; use memchr::memchr2;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Macros<'a> { pub struct Macros<'a> {
pub name: &'a str, pub name: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub arguments: Option<&'a str>, pub arguments: Option<&'a str>,
} }

View file

@ -20,7 +20,7 @@ mod snippet;
mod target; mod target;
mod timestamp; mod timestamp;
pub mod emphasis; pub(crate) mod emphasis;
pub use self::{ pub use self::{
block::Block, block::Block,
@ -48,187 +48,304 @@ pub use self::{
use indextree::NodeId; use indextree::NodeId;
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum Element<'a> { pub enum Element<'a> {
Root, Root,
Block { Block {
#[cfg_attr(feature = "serde", serde(flatten))]
block: Block<'a>, block: Block<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
BabelCall { BabelCall {
#[cfg_attr(feature = "serde", serde(flatten))]
call: BabelCall<'a>, call: BabelCall<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Section { Section {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Clock { Clock {
#[cfg_attr(feature = "serde", serde(flatten))]
clock: Clock<'a>, clock: Clock<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Cookie { Cookie {
#[cfg_attr(feature = "serde", serde(flatten))]
cookie: Cookie<'a>, cookie: Cookie<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
RadioTarget { RadioTarget {
#[cfg_attr(feature = "serde", serde(flatten))]
radio_target: RadioTarget<'a>, radio_target: RadioTarget<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Drawer { Drawer {
#[cfg_attr(feature = "serde", serde(flatten))]
drawer: Drawer<'a>, drawer: Drawer<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Document { Document {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
DynBlock { DynBlock {
#[cfg_attr(feature = "serde", serde(flatten))]
dyn_block: DynBlock<'a>, dyn_block: DynBlock<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
FnDef { FnDef {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
fn_def: FnDef<'a>, fn_def: FnDef<'a>,
}, },
FnRef { FnRef {
#[cfg_attr(feature = "serde", serde(flatten))]
fn_ref: FnRef<'a>, fn_ref: FnRef<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Headline { Headline {
begin: usize, #[cfg_attr(feature = "serde", serde(flatten))]
end: usize,
contents_begin: usize,
contents_end: usize,
headline: Headline<'a>, headline: Headline<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize,
}, },
InlineCall { InlineCall {
#[cfg_attr(feature = "serde", serde(flatten))]
inline_call: InlineCall<'a>, inline_call: InlineCall<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
InlineSrc { InlineSrc {
#[cfg_attr(feature = "serde", serde(flatten))]
inline_src: InlineSrc<'a>, inline_src: InlineSrc<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Keyword { Keyword {
#[cfg_attr(feature = "serde", serde(flatten))]
keyword: Keyword<'a>, keyword: Keyword<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Link { Link {
#[cfg_attr(feature = "serde", serde(flatten))]
link: Link<'a>, link: Link<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
List { List {
#[cfg_attr(feature = "serde", serde(flatten))]
list: List, list: List,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
ListItem { ListItem {
#[cfg_attr(feature = "serde", serde(flatten))]
list_item: ListItem<'a>, list_item: ListItem<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Macros { Macros {
#[cfg_attr(feature = "serde", serde(flatten))]
macros: Macros<'a>, macros: Macros<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Planning { Planning {
#[cfg_attr(feature = "serde", serde(skip))]
deadline: Option<NodeId>, deadline: Option<NodeId>,
#[cfg_attr(feature = "serde", serde(skip))]
scheduled: Option<NodeId>, scheduled: Option<NodeId>,
#[cfg_attr(feature = "serde", serde(skip))]
closed: Option<NodeId>, closed: Option<NodeId>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Snippet { Snippet {
begin: usize, #[cfg_attr(feature = "serde", serde(flatten))]
end: usize,
snippet: Snippet<'a>, snippet: Snippet<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize,
}, },
Text { Text {
value: &'a str, value: &'a str,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Paragraph { Paragraph {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Rule { Rule {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Timestamp { Timestamp {
begin: usize, #[cfg_attr(feature = "serde", serde(flatten))]
end: usize,
timestamp: Timestamp<'a>, timestamp: Timestamp<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize,
}, },
Target { Target {
#[cfg_attr(feature = "serde", serde(flatten))]
target: Target<'a>, target: Target<'a>,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
}, },
Bold { Bold {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Strike { Strike {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Italic { Italic {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Underline { Underline {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_begin: usize, contents_begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
contents_end: usize, contents_end: usize,
}, },
Verbatim { Verbatim {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
value: &'a str, value: &'a str,
}, },
Code { Code {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize, begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize, end: usize,
value: &'a str, value: &'a str,
}, },

View file

@ -3,13 +3,17 @@ use memchr::memchr;
/// palnning elements /// palnning elements
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Planning<'a> { pub struct Planning<'a> {
/// the date when the task should be done /// the date when the task should be done
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub deadline: Option<&'a Timestamp<'a>>, pub deadline: Option<&'a Timestamp<'a>>,
/// the date when you should start working on the task /// the date when you should start working on the task
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub scheduled: Option<&'a Timestamp<'a>>, pub scheduled: Option<&'a Timestamp<'a>>,
/// the date when the task is closed /// the date when the task is closed
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub closed: Option<&'a Timestamp<'a>>, pub closed: Option<&'a Timestamp<'a>>,
} }

View file

@ -2,6 +2,7 @@ use jetscii::Substring;
// TODO: text-markup, entities, latex-fragments, subscript and superscript // TODO: text-markup, entities, latex-fragments, subscript and superscript
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct RadioTarget<'a> { pub struct RadioTarget<'a> {
contents: &'a str, contents: &'a str,

View file

@ -2,6 +2,7 @@ use jetscii::Substring;
use memchr::memchr; use memchr::memchr;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Snippet<'a> { pub struct Snippet<'a> {
pub name: &'a str, pub name: &'a str,

View file

@ -1,6 +1,7 @@
use jetscii::Substring; use jetscii::Substring;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub struct Target<'a> { pub struct Target<'a> {
pub target: &'a str, pub target: &'a str,

View file

@ -2,9 +2,11 @@ use memchr::memchr;
use std::str::FromStr; use std::str::FromStr;
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Datetime<'a> { pub struct Datetime<'a> {
pub(crate) date: &'a str, pub(crate) date: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub(crate) time: Option<&'a str>, pub(crate) time: Option<&'a str>,
pub(crate) dayname: &'a str, pub(crate) dayname: &'a str,
} }
@ -76,7 +78,8 @@ mod chrono {
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Copy, Clone)]
pub enum RepeaterType { pub enum RepeaterType {
Cumulate, Cumulate,
CatchUp, CatchUp,
@ -84,6 +87,7 @@ pub enum RepeaterType {
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum DelayType { pub enum DelayType {
All, All,
@ -91,6 +95,7 @@ pub enum DelayType {
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum TimeUnit { pub enum TimeUnit {
Hour, Hour,
@ -101,6 +106,7 @@ pub enum TimeUnit {
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Repeater { pub struct Repeater {
pub ty: RepeaterType, pub ty: RepeaterType,
@ -109,6 +115,7 @@ pub struct Repeater {
} }
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Delay { pub struct Delay {
pub ty: DelayType, pub ty: DelayType,
@ -118,28 +125,37 @@ pub struct Delay {
/// timestamp obejcts /// timestamp obejcts
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Debug)] #[derive(Debug)]
pub enum Timestamp<'a> { pub enum Timestamp<'a> {
Active { Active {
start: Datetime<'a>, start: Datetime<'a>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
repeater: Option<&'a str>, repeater: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
delay: Option<&'a str>, delay: Option<&'a str>,
}, },
Inactive { Inactive {
start: Datetime<'a>, start: Datetime<'a>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
repeater: Option<&'a str>, repeater: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
delay: Option<&'a str>, delay: Option<&'a str>,
}, },
ActiveRange { ActiveRange {
start: Datetime<'a>, start: Datetime<'a>,
end: Datetime<'a>, end: Datetime<'a>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
repeater: Option<&'a str>, repeater: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
delay: Option<&'a str>, delay: Option<&'a str>,
}, },
InactiveRange { InactiveRange {
start: Datetime<'a>, start: Datetime<'a>,
end: Datetime<'a>, end: Datetime<'a>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
repeater: Option<&'a str>, repeater: Option<&'a str>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
delay: Option<&'a str>, delay: Option<&'a str>,
}, },
Diary(&'a str), Diary(&'a str),

View file

@ -1,5 +1,5 @@
use indextree::{Arena, NodeId}; use indextree::{Arena, NodeId};
use serde::ser::{SerializeSeq, SerializeStruct, Serializer}; use serde::ser::{SerializeSeq, Serializer};
use serde::Serialize; use serde::Serialize;
use crate::elements::Element; use crate::elements::Element;
@ -7,417 +7,27 @@ use crate::org::Org;
impl Serialize for Org<'_> { impl Serialize for Org<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_newtype_struct( serializer
"Element", .serialize_newtype_struct("ElementNode", &ElementNode::new(self.document, &self.arena))
&ElementNode {
node: self.document,
arena: &self.arena,
},
)
} }
} }
#[derive(Serialize)]
struct ElementNode<'a> { struct ElementNode<'a> {
node: NodeId, #[serde(flatten)]
arena: &'a Arena<Element<'a>>, element: &'a Element<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
children: Option<ElementChildrenNode<'a>>,
} }
impl Serialize for ElementNode<'_> { impl<'a> ElementNode<'a> {
#[allow(unused_variables)] fn new(node_id: NodeId, arena: &'a Arena<Element<'a>>) -> Self {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { let node = &arena[node_id];
let node = &self.arena[self.node]; ElementNode {
element: &node.data,
macro_rules! ser { children: node
($state:ident, $begin:ident, $end:ident) => { .first_child()
if cfg!(feature = "extra-serde-info") { .map(|first| ElementChildrenNode { first, arena }),
$state.serialize_field("begin", $begin)?;
$state.serialize_field("end", $end)?;
}
};
($state:ident, $begin:ident, $end:ident, $contents_begin:ident, $contents_end:ident) => {
if cfg!(feature = "extra-serde-info") {
$state.serialize_field("begin", $begin)?;
$state.serialize_field("end", $end)?;
$state.serialize_field("contents_begin", $contents_begin)?;
$state.serialize_field("contents_end", $contents_end)?;
}
if let Some(first) = node.first_child() {
$state.serialize_field(
"children",
&ElementChildrenNode {
first,
arena: self.arena,
},
)?;
}
};
}
match &node.data {
Element::Root => {
let mut state = serializer.serialize_struct("Element::Root", 2)?;
state.serialize_field("type", "root")?;
if let Some(first) = node.first_child() {
state.serialize_field(
"children",
&ElementChildrenNode {
first,
arena: self.arena,
},
)?;
}
state.end()
}
Element::Document {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Document", 2)?;
state.serialize_field("type", "document")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Block {
block,
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Block", 2)?;
state.serialize_field("type", "block")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Section {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Section", 2)?;
state.serialize_field("type", "section")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Drawer {
drawer,
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Drawer", 2)?;
state.serialize_field("type", "drawer")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::DynBlock {
dyn_block,
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::DynBlock", 2)?;
state.serialize_field("type", "dynamic_block")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::FnDef {
begin,
end,
contents_begin,
contents_end,
fn_def,
} => {
let mut state = serializer.serialize_struct("Element::FnDef", 2)?;
state.serialize_field("type", "footnote_definition")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Headline {
begin,
end,
contents_begin,
contents_end,
headline,
} => {
let mut state = serializer.serialize_struct("Element::Headline", 6)?;
state.serialize_field("type", "headline")?;
state.serialize_field("level", &headline.level)?;
state.serialize_field("title", &headline.title)?;
if let Some(prior) = &headline.priority {
state.serialize_field("priority", prior)?;
}
if let Some(kw) = &headline.keyword {
state.serialize_field("keyword", kw)?;
}
if !headline.tags.is_empty() {
state.serialize_field("tags", &headline.tags)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::List {
list,
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::List", 2)?;
state.serialize_field("type", "list")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::ListItem {
list_item,
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::ListItem", 3)?;
state.serialize_field("type", "list_item")?;
state.serialize_field("bullet", list_item.bullet)?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Paragraph {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Paragraph", 2)?;
state.serialize_field("type", "paragraph")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Clock { clock, begin, end } => {
let mut state = serializer.serialize_struct("Element::Clock", 1)?;
state.serialize_field("type", "clock")?;
ser!(state, begin, end);
state.end()
}
Element::BabelCall { call, begin, end } => {
let mut state = serializer.serialize_struct("Element::BabelCall", 1)?;
state.serialize_field("type", "babel_call")?;
ser!(state, begin, end);
state.end()
}
Element::Cookie { cookie, begin, end } => {
let mut state = serializer.serialize_struct("Element::Cookie", 1)?;
state.serialize_field("type", "cookie")?;
ser!(state, begin, end);
state.end()
}
Element::FnRef { fn_ref, begin, end } => {
let mut state = serializer.serialize_struct("Element::FnRef", 1)?;
state.serialize_field("type", "footnote_reference")?;
ser!(state, begin, end);
state.end()
}
Element::InlineCall {
inline_call,
begin,
end,
} => {
let mut state = serializer.serialize_struct("Element::InlineCall", 1)?;
state.serialize_field("type", "inline_call")?;
ser!(state, begin, end);
state.end()
}
Element::InlineSrc {
inline_src,
begin,
end,
} => {
let mut state = serializer.serialize_struct("Element::InlineSrc", 1)?;
state.serialize_field("type", "inlne_source_block")?;
ser!(state, begin, end);
state.end()
}
Element::Keyword {
keyword,
begin,
end,
} => {
let mut state = serializer.serialize_struct("Element::Keyword", 4)?;
state.serialize_field("type", "keyword")?;
state.serialize_field("key", keyword.key)?;
if let Some(option) = keyword.option {
state.serialize_field("option", option)?;
}
state.serialize_field("value", keyword.value)?;
ser!(state, begin, end);
state.end()
}
Element::Link { link, begin, end } => {
let mut state = serializer.serialize_struct("Element::Link", 3)?;
state.serialize_field("type", "link")?;
state.serialize_field("path", link.path)?;
if let Some(desc) = link.desc {
state.serialize_field("desc", desc)?;
}
ser!(state, begin, end);
state.end()
}
Element::Macros { macros, begin, end } => {
let mut state = serializer.serialize_struct("Element::Macros", 1)?;
state.serialize_field("type", "macros")?;
ser!(state, begin, end);
state.end()
}
Element::Planning {
deadline,
scheduled,
closed,
begin,
end,
} => {
let mut state = serializer.serialize_struct("Element::Planning", 4)?;
state.serialize_field("type", "planning")?;
if let Some(node) = deadline {
state.serialize_field(
"deadline",
&ElementNode {
node: *node,
arena: &self.arena,
},
)?;
}
if let Some(node) = closed {
state.serialize_field(
"closed",
&ElementNode {
node: *node,
arena: &self.arena,
},
)?;
}
if let Some(node) = scheduled {
state.serialize_field(
"scheduled",
&ElementNode {
node: *node,
arena: &self.arena,
},
)?;
}
ser!(state, begin, end);
state.end()
}
Element::Snippet {
begin,
end,
snippet,
} => {
let mut state = serializer.serialize_struct("Element::Snippet", 2)?;
state.serialize_field("type", "snippet")?;
ser!(state, begin, end);
state.end()
}
Element::Text { value, begin, end } => {
let mut state = serializer.serialize_struct("Element::Text", 2)?;
state.serialize_field("type", "text")?;
state.serialize_field("value", value)?;
ser!(state, begin, end);
state.end()
}
Element::Rule { begin, end } => {
let mut state = serializer.serialize_struct("Element::Rule", 1)?;
state.serialize_field("type", "rule")?;
ser!(state, begin, end);
state.end()
}
Element::Timestamp {
begin,
end,
timestamp,
} => {
let mut state = serializer.serialize_struct("Element::Timestamp", 1)?;
state.serialize_field("type", "timestamp")?;
ser!(state, begin, end);
state.end()
}
Element::Bold {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Bold", 2)?;
state.serialize_field("type", "bold")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Strike {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Strike", 2)?;
state.serialize_field("type", "strike")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Italic {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Italic", 2)?;
state.serialize_field("type", "italic")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Underline {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Underline", 2)?;
state.serialize_field("type", "underline")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Code { begin, end, value } => {
let mut state = serializer.serialize_struct("Element::Code", 2)?;
state.serialize_field("type", "code")?;
state.serialize_field("value", value)?;
ser!(state, begin, end);
state.end()
}
Element::Verbatim { begin, end, value } => {
let mut state = serializer.serialize_struct("Element::Verbatim", 2)?;
state.serialize_field("type", "verbatim")?;
state.serialize_field("value", value)?;
ser!(state, begin, end);
state.end()
}
Element::RadioTarget {
radio_target,
begin,
end,
} => {
let mut state = serializer.serialize_struct("Element::RadioTarget", 1)?;
state.serialize_field("type", "radio_target")?;
ser!(state, begin, end);
state.end()
}
Element::Target { target, begin, end } => {
let mut state = serializer.serialize_struct("Element::Target", 1)?;
state.serialize_field("type", "target")?;
ser!(state, begin, end);
state.end()
}
} }
} }
} }
@ -431,10 +41,7 @@ impl Serialize for ElementChildrenNode<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_seq(None)?; let mut seq = serializer.serialize_seq(None)?;
for node in self.first.following_siblings(&self.arena) { for node in self.first.following_siblings(&self.arena) {
seq.serialize_element(&ElementNode { seq.serialize_element(&ElementNode::new(node, &self.arena))?;
node,
arena: &self.arena,
})?;
} }
seq.end() seq.end()
} }