feat(elements): planning element

This commit is contained in:
PoiScript 2019-06-27 13:20:21 +08:00
parent 74fd77dba2
commit 2cba072245
10 changed files with 341 additions and 256 deletions

View file

@ -9,7 +9,7 @@ use test::Bencher;
fn org_syntax(b: &mut Bencher) {
// wget https://orgmode.org/worg/sources/dev/org-syntax.org
b.iter(|| {
Org::new(include_str!("org-syntax.org")).parse();
Org::parse(include_str!("org-syntax.org"));
})
}
@ -17,7 +17,7 @@ fn org_syntax(b: &mut Bencher) {
fn doc(b: &mut Bencher) {
// wget https://orgmode.org/worg/sources/doc.org
b.iter(|| {
Org::new(include_str!("doc.org")).parse();
Org::parse(include_str!("doc.org"));
})
}
@ -25,6 +25,6 @@ fn doc(b: &mut Bencher) {
fn org_faq(b: &mut Bencher) {
// wget https://orgmode.org/worg/sources/org-faq.org
b.iter(|| {
Org::new(include_str!("org-faq.org")).parse();
Org::parse(include_str!("org-faq.org"));
})
}

View file

@ -60,11 +60,9 @@ fn main() -> Result<(), MyError> {
eprintln!("Usage: {} <org-file>", args[0]);
} else {
let contents = String::from_utf8(fs::read(&args[1])?)?;
let mut org = Org::new(&contents);
let mut writer = Vec::new();
org.parse();
org.html(&mut writer, CustomHtmlHandler)?;
let mut writer = Vec::new();
Org::parse(&contents).html(&mut writer, CustomHtmlHandler)?;
println!("{}", String::from_utf8(writer)?);
}

View file

@ -11,9 +11,7 @@ fn main() -> Result<()> {
eprintln!("Usage: {} <org-file>", args[0]);
} else {
let contents = String::from_utf8(fs::read(&args[1])?).unwrap();
let mut org = Org::new(&contents);
org.parse();
println!("{}", to_string(&org).unwrap());
println!("{}", to_string(&Org::parse(&contents)).unwrap());
}
Ok(())
}

View file

@ -3,7 +3,7 @@
use jetscii::ByteSubstring;
use memchr::{memchr, memchr2, memrchr};
pub(crate) const DEFAULT_TODO_KEYWORDS: &[&str] =
pub const DEFAULT_TODO_KEYWORDS: &[&str] =
&["TODO", "DONE", "NEXT", "WAITING", "LATER", "CANCELLED"];
#[cfg_attr(test, derive(PartialEq))]

View file

@ -30,7 +30,7 @@ pub use self::{
dyn_block::DynBlock,
fn_def::FnDef,
fn_ref::FnRef,
headline::Headline,
headline::{Headline, DEFAULT_TODO_KEYWORDS},
inline_call::InlineCall,
inline_src::InlineSrc,
keyword::{BabelCall, Keyword},
@ -45,6 +45,8 @@ pub use self::{
timestamp::*,
};
use indextree::NodeId;
#[derive(Debug)]
pub enum Element<'a> {
Root,
@ -91,6 +93,8 @@ pub enum Element<'a> {
Document {
begin: usize,
end: usize,
contents_begin: usize,
contents_end: usize,
},
DynBlock {
dyn_block: DynBlock<'a>,
@ -157,7 +161,13 @@ pub enum Element<'a> {
begin: usize,
end: usize,
},
Planning(Planning<'a>),
Planning {
deadline: Option<NodeId>,
scheduled: Option<NodeId>,
closed: Option<NodeId>,
begin: usize,
end: usize,
},
Snippet {
begin: usize,
end: usize,

View file

@ -6,16 +6,24 @@ use memchr::memchr;
#[derive(Debug)]
pub struct Planning<'a> {
/// the date when the task should be done
pub deadline: Option<Timestamp<'a>>,
pub deadline: Option<&'a Timestamp<'a>>,
/// the date when you should start working on the task
pub scheduled: Option<Timestamp<'a>>,
pub scheduled: Option<&'a Timestamp<'a>>,
/// the date when the task is closed
pub closed: Option<Timestamp<'a>>,
pub closed: Option<&'a Timestamp<'a>>,
}
impl Planning<'_> {
#[inline]
pub(crate) fn parse(text: &str) -> Option<(Planning<'_>, usize)> {
pub(crate) fn parse(
text: &str,
) -> Option<(
// TODO: timestamp position
Option<(Timestamp<'_>, usize, usize)>,
Option<(Timestamp<'_>, usize, usize)>,
Option<(Timestamp<'_>, usize, usize)>,
usize,
)> {
let (mut deadline, mut scheduled, mut closed) = (None, None, None);
let (mut tail, off) = memchr(b'\n', text.as_bytes())
.map(|i| (text[..i].trim(), i + 1))
@ -28,7 +36,7 @@ impl Planning<'_> {
($timestamp:expr) => {
if $timestamp.is_none() {
let (timestamp, off) = Timestamp::parse(next)?;
$timestamp = Some(timestamp);
$timestamp = Some((timestamp, 0, 0));
tail = &next[off..].trim_start();
} else {
return None;
@ -47,14 +55,7 @@ impl Planning<'_> {
if deadline.is_none() && scheduled.is_none() && closed.is_none() {
None
} else {
Some((
Planning {
deadline,
scheduled,
closed,
},
off,
))
Some((deadline, scheduled, closed, off))
}
}
}
@ -66,8 +67,9 @@ fn prase() {
assert_eq!(
Planning::parse("SCHEDULED: <2019-04-08 Mon>\n"),
Some((
Planning {
scheduled: Some(Timestamp::Active {
None,
Some((
Timestamp::Active {
start: Datetime {
date: "2019-04-08",
time: None,
@ -75,10 +77,11 @@ fn prase() {
},
repeater: None,
delay: None
}),
closed: None,
deadline: None,
},
},
0,
0
)),
None,
"SCHEDULED: <2019-04-08 Mon>\n".len()
))
)

View file

@ -32,7 +32,7 @@ pub enum Event<'a> {
Keyword(&'a Keyword<'a>),
Link(&'a Link<'a>),
Macros(&'a Macros<'a>),
Planning(&'a Planning<'a>),
Planning(Planning<'a>),
RadioTarget(&'a RadioTarget<'a>),
Rule,
Snippet(&'a Snippet<'a>),
@ -226,9 +226,36 @@ impl<'a> Iter<'a> {
self.state = State::Start;
Some(Event::Macros(macros))
}
Element::Planning(planning) => {
Element::Planning {
deadline,
scheduled,
closed,
..
} => {
self.state = State::Start;
Some(Event::Planning(planning))
Some(Event::Planning(Planning {
deadline: deadline.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
scheduled: scheduled.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
closed: closed.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
}))
}
Element::RadioTarget { radio_target, .. } => {
self.state = State::Start;
@ -364,9 +391,36 @@ impl<'a> Iter<'a> {
self.state = State::End;
Some(Event::Macros(macros))
}
Element::Planning(planning) => {
Element::Planning {
deadline,
scheduled,
closed,
..
} => {
self.state = State::End;
Some(Event::Planning(planning))
Some(Event::Planning(Planning {
deadline: deadline.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
scheduled: scheduled.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
closed: closed.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
}))
}
Element::RadioTarget { radio_target, .. } => {
self.state = State::End;

View file

@ -1,12 +1,12 @@
use crate::elements::*;
use crate::export::{DefaultHtmlHandler, HtmlHandler};
use crate::iter::Iter;
use indextree::{Arena, NodeId};
use jetscii::bytes;
use memchr::{memchr, memchr_iter, memrchr_iter};
use std::io::{Error, Write};
use crate::elements::*;
use crate::export::{DefaultHtmlHandler, HtmlHandler};
use crate::iter::Iter;
pub struct Org<'a> {
pub(crate) arena: Arena<Element<'a>>,
pub(crate) document: NodeId,
@ -15,25 +15,26 @@ pub struct Org<'a> {
}
impl<'a> Org<'a> {
pub fn new(text: &'a str) -> Self {
pub fn parse(text: &'a str) -> Self {
let mut arena = Arena::new();
let root = arena.new_node(Element::Root);
let document = arena.new_node(Element::Document {
begin: 0,
end: text.len(),
contents_begin: 0,
contents_end: text.len(),
});
root.append(document, &mut arena).unwrap();
Org {
let mut org = Org {
arena,
root,
document,
text,
}
}
};
org.parse_internal();
pub fn finish(&self) -> bool {
self.arena[self.document].first_child().is_some()
org
}
pub fn iter(&'a self) -> Iter<'a> {
@ -62,7 +63,7 @@ impl<'a> Org<'a> {
Keyword(e) => handler.keyword(&mut writer, e)?,
Link(e) => handler.link(&mut writer, e)?,
Macros(e) => handler.macros(&mut writer, e)?,
Planning(e) => handler.planning(&mut writer, e)?,
Planning(e) => handler.planning(&mut writer, &e)?,
RadioTarget(e) => handler.radio_target(&mut writer, e)?,
Snippet(e) => handler.snippet(&mut writer, e)?,
Target(e) => handler.target(&mut writer, e)?,
@ -82,15 +83,15 @@ impl<'a> Org<'a> {
self.html(wrtier, DefaultHtmlHandler)
}
pub fn parse(&mut self) {
if self.finish() {
return;
}
fn parse_internal(&mut self) {
let mut node = self.document;
loop {
match self.arena[node].data {
Element::Document { begin, end, .. }
Element::Document {
contents_begin: begin,
contents_end: end,
..
}
| Element::Headline {
contents_begin: begin,
contents_end: end,
@ -131,8 +132,51 @@ impl<'a> Org<'a> {
contents_begin,
contents_end,
..
} => {
let (mut deadline_node, mut scheduled_node, mut closed_node) =
(None, None, None);
if let Some((deadline, scheduled, closed, off)) =
Planning::parse(&self.text[contents_begin..contents_end])
{
if let Some((deadline, off, end)) = deadline {
let timestamp = Element::Timestamp {
timestamp: deadline,
begin: contents_begin + off,
end: contents_end + end,
};
deadline_node = Some(self.arena.new_node(timestamp));
}
if let Some((scheduled, off, end)) = scheduled {
let timestamp = Element::Timestamp {
timestamp: scheduled,
begin: contents_begin + off,
end: contents_end + end,
};
scheduled_node = Some(self.arena.new_node(timestamp));
}
if let Some((closed, off, end)) = closed {
let timestamp = Element::Timestamp {
timestamp: closed,
begin: contents_begin + off,
end: contents_end + end,
};
closed_node = Some(self.arena.new_node(timestamp));
}
let planning = Element::Planning {
deadline: deadline_node,
scheduled: scheduled_node,
closed: closed_node,
begin: contents_begin,
end: contents_begin + off,
};
let new_node = self.arena.new_node(planning);
node.append(new_node, &mut self.arena).unwrap();
self.parse_elements_children(contents_begin + off, contents_end, node);
} else {
self.parse_elements_children(contents_begin, contents_end, node);
}
}
| Element::Block {
Element::Block {
contents_begin,
contents_end,
..

View file

@ -25,19 +25,59 @@ struct ElementNode<'a> {
impl Serialize for ElementNode<'_> {
#[allow(unused_variables)]
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut state;
match &self.arena[self.node].data {
Element::Root => {
state = serializer.serialize_struct("Element::Root", 2)?;
state.serialize_field("type", "root")?;
}
Element::Document { begin, end } => {
state = serializer.serialize_struct("Element::Document", 2)?;
state.serialize_field("type", "document")?;
let node = &self.arena[self.node];
macro_rules! ser {
($state:ident, $begin:ident, $end:ident) => {
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
$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,
@ -46,14 +86,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Block", 2)?;
let mut state = serializer.serialize_struct("Element::Block", 2)?;
state.serialize_field("type", "block")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Section {
begin,
@ -61,14 +97,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Section", 2)?;
let mut state = serializer.serialize_struct("Element::Section", 2)?;
state.serialize_field("type", "section")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Drawer {
drawer,
@ -77,14 +109,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Drawer", 2)?;
let mut state = serializer.serialize_struct("Element::Drawer", 2)?;
state.serialize_field("type", "drawer")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::DynBlock {
dyn_block,
@ -93,14 +121,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::DynBlock", 2)?;
let mut state = serializer.serialize_struct("Element::DynBlock", 2)?;
state.serialize_field("type", "dynamic_block")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::FnDef {
begin,
@ -109,14 +133,10 @@ impl Serialize for ElementNode<'_> {
contents_end,
fn_def,
} => {
state = serializer.serialize_struct("Element::FnDef", 2)?;
let mut state = serializer.serialize_struct("Element::FnDef", 2)?;
state.serialize_field("type", "footnote_definition")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Headline {
begin,
@ -125,7 +145,7 @@ impl Serialize for ElementNode<'_> {
contents_end,
headline,
} => {
state = serializer.serialize_struct("Element::Headline", 2)?;
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)?;
@ -138,12 +158,8 @@ impl Serialize for ElementNode<'_> {
if !headline.tags.is_empty() {
state.serialize_field("tags", &headline.tags)?;
}
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::List {
list,
@ -152,14 +168,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::List", 2)?;
let mut state = serializer.serialize_struct("Element::List", 2)?;
state.serialize_field("type", "list")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::ListItem {
list_item,
@ -168,15 +180,11 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::ListItem", 2)?;
let mut state = serializer.serialize_struct("Element::ListItem", 3)?;
state.serialize_field("type", "list_item")?;
state.serialize_field("bullet", list_item.bullet)?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Paragraph {
begin,
@ -184,152 +192,157 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Paragraph", 2)?;
let mut state = serializer.serialize_struct("Element::Paragraph", 2)?;
state.serialize_field("type", "paragraph")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Clock { clock, begin, end } => {
state = serializer.serialize_struct("Element::Clock", 2)?;
let mut state = serializer.serialize_struct("Element::Clock", 1)?;
state.serialize_field("type", "clock")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::BabelCall { call, begin, end } => {
state = serializer.serialize_struct("Element::BabelCall", 2)?;
let mut state = serializer.serialize_struct("Element::BabelCall", 1)?;
state.serialize_field("type", "babel_call")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Cookie { cookie, begin, end } => {
state = serializer.serialize_struct("Element::Cookie", 2)?;
let mut state = serializer.serialize_struct("Element::Cookie", 1)?;
state.serialize_field("type", "cookie")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::FnRef { fn_ref, begin, end } => {
state = serializer.serialize_struct("Element::FnRef", 2)?;
let mut state = serializer.serialize_struct("Element::FnRef", 1)?;
state.serialize_field("type", "footnote_reference")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::InlineCall {
inline_call,
begin,
end,
} => {
state = serializer.serialize_struct("Element::InlineCall", 2)?;
let mut state = serializer.serialize_struct("Element::InlineCall", 1)?;
state.serialize_field("type", "inline_call")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::InlineSrc {
inline_src,
begin,
end,
} => {
state = serializer.serialize_struct("Element::InlineSrc", 2)?;
let mut state = serializer.serialize_struct("Element::InlineSrc", 1)?;
state.serialize_field("type", "inlne_source_block")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Keyword {
keyword,
begin,
end,
} => {
state = serializer.serialize_struct("Element::Keyword", 2)?;
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)?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Link { link, begin, end } => {
state = serializer.serialize_struct("Element::Link", 2)?;
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)?;
}
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Macros { macros, begin, end } => {
state = serializer.serialize_struct("Element::Macros", 2)?;
let mut state = serializer.serialize_struct("Element::Macros", 1)?;
state.serialize_field("type", "macros")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Planning(_) => {
state = serializer.serialize_struct("Element::Planning", 2)?;
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,
} => {
state = serializer.serialize_struct("Element::Snippet", 2)?;
let mut state = serializer.serialize_struct("Element::Snippet", 2)?;
state.serialize_field("type", "snippet")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Text { value, begin, end } => {
state = serializer.serialize_struct("Element::Text", 2)?;
let mut state = serializer.serialize_struct("Element::Text", 2)?;
state.serialize_field("type", "text")?;
state.serialize_field("value", value)?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Rule { begin, end } => {
state = serializer.serialize_struct("Element::Rule", 2)?;
let mut state = serializer.serialize_struct("Element::Rule", 1)?;
state.serialize_field("type", "rule")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Timestamp {
begin,
end,
timestamp,
} => {
state = serializer.serialize_struct("Element::Timestamp", 2)?;
let mut state = serializer.serialize_struct("Element::Timestamp", 1)?;
state.serialize_field("type", "timestamp")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Bold {
begin,
@ -337,14 +350,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Bold", 2)?;
let mut state = serializer.serialize_struct("Element::Bold", 2)?;
state.serialize_field("type", "bold")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Strike {
begin,
@ -352,14 +361,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Strike", 2)?;
let mut state = serializer.serialize_struct("Element::Strike", 2)?;
state.serialize_field("type", "strike")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Italic {
begin,
@ -367,14 +372,10 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Italic", 2)?;
let mut state = serializer.serialize_struct("Element::Italic", 2)?;
state.serialize_field("type", "italic")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Underline {
begin,
@ -382,64 +383,42 @@ impl Serialize for ElementNode<'_> {
contents_begin,
contents_end,
} => {
state = serializer.serialize_struct("Element::Underline", 2)?;
let mut state = serializer.serialize_struct("Element::Underline", 2)?;
state.serialize_field("type", "underline")?;
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)?;
}
ser!(state, begin, end, contents_begin, contents_end);
state.end()
}
Element::Code { begin, end, value } => {
state = serializer.serialize_struct("Element::Code", 2)?;
let mut state = serializer.serialize_struct("Element::Code", 2)?;
state.serialize_field("type", "code")?;
state.serialize_field("value", value)?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Verbatim { begin, end, value } => {
state = serializer.serialize_struct("Element::Verbatim", 2)?;
let mut state = serializer.serialize_struct("Element::Verbatim", 2)?;
state.serialize_field("type", "verbatim")?;
state.serialize_field("value", value)?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::RadioTarget {
radio_target,
begin,
end,
} => {
state = serializer.serialize_struct("Element::RadioTarget", 2)?;
let mut state = serializer.serialize_struct("Element::RadioTarget", 1)?;
state.serialize_field("type", "radio_target")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
Element::Target { target, begin, end } => {
state = serializer.serialize_struct("Element::Target", 2)?;
let mut state = serializer.serialize_struct("Element::Target", 1)?;
state.serialize_field("type", "target")?;
if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?;
state.serialize_field("end", end)?;
}
ser!(state, begin, end);
state.end()
}
}
if let Some(first) = self.arena[self.node].first_child() {
state.serialize_field(
"children",
&ElementChildrenNode {
first,
arena: self.arena,
},
)?;
}
state.end()
}
}

View file

@ -6,8 +6,7 @@ macro_rules! test_suite {
#[test]
fn $name() {
let mut writer = Vec::new();
let mut org = Org::new($content);
org.parse();
let org = Org::parse($content);
org.html_default(&mut writer).unwrap();
let string = String::from_utf8(writer).unwrap();
assert_eq!(string, $expected);