Add a utility function to check the first element in an sexp.

This commit is contained in:
Tom Alexander 2023-04-19 15:19:21 -04:00
parent 821eacf161
commit a4c6e899ac
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 49 additions and 83 deletions

View File

@ -1,4 +1,5 @@
use super::sexp::Token;
use super::util::assert_name;
use crate::compare::util::get_offsets;
use crate::parser::Comment;
use crate::parser::Document;
@ -18,6 +19,7 @@ use crate::DynamicBlock;
pub struct DiffResult {
status: DiffStatus,
name: String,
message: Option<String>,
children: Vec<DiffResult>,
}
@ -71,11 +73,7 @@ pub fn compare_document<'s>(
rust: &'s Document<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children.first().ok_or("Should have at least one child.")?;
let first_child_text = first_child.as_atom()?;
if first_child_text != "org-data" {
return Err("Document should correspond to an org-data cell.".into());
}
assert_name(emacs, "org-data")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -112,6 +110,7 @@ pub fn compare_document<'s>(
Ok(DiffResult {
status: this_status,
name: "document".to_owned(),
message: None,
children: child_status,
})
}
@ -122,11 +121,7 @@ fn compare_section<'s>(
rust: &'s Section<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children.first().ok_or("Should have at least one child.")?;
let first_child_text = first_child.as_atom()?;
if first_child_text != "section" {
return Err("Section should correspond to a section cell.".into());
}
assert_name(emacs, "section")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -155,6 +150,7 @@ fn compare_section<'s>(
Ok(DiffResult {
status: this_status,
name: "section".to_owned(),
message: None,
children: child_status,
})
}
@ -165,11 +161,7 @@ fn compare_heading<'s>(
rust: &'s Heading<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children.first().ok_or("Should have at least one child.")?;
let first_child_text = first_child.as_atom()?;
if first_child_text != "headline" {
return Err("Heading should correspond to a headline cell.".into());
}
assert_name(emacs, "headline")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -205,6 +197,7 @@ fn compare_heading<'s>(
Ok(DiffResult {
status: this_status,
name: "heading".to_owned(),
message: None,
children: child_status,
})
}
@ -231,13 +224,7 @@ fn compare_paragraph<'s>(
rust: &'s Paragraph<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "paragraph" {
return Err("Paragraph should correspond to a paragraph cell.".into());
}
assert_name(emacs, "paragraph")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -264,6 +251,7 @@ fn compare_paragraph<'s>(
Ok(DiffResult {
status: this_status,
name: "paragraph".to_owned(),
message: None,
children: child_status,
})
}
@ -274,13 +262,7 @@ fn compare_plain_list<'s>(
rust: &'s PlainList<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "plain-list" {
return Err("Paragraph should correspond to a paragraph cell.".into());
}
assert_name(emacs, "plain-list")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -309,6 +291,7 @@ fn compare_plain_list<'s>(
Ok(DiffResult {
status: this_status,
name: "plain-list".to_owned(),
message: None,
children: child_status,
})
}
@ -319,13 +302,7 @@ fn compare_plain_list_item<'s>(
rust: &'s PlainListItem<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "item" {
return Err("PlainListItem should correspond to an item cell.".into());
}
assert_name(emacs, "item")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -354,6 +331,7 @@ fn compare_plain_list_item<'s>(
Ok(DiffResult {
status: this_status,
name: "plain-list-item".to_owned(),
message: None,
children: child_status,
})
}
@ -364,25 +342,14 @@ fn compare_greater_block<'s>(
rust: &'s GreaterBlock<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
assert_name(
emacs,
match rust.name.to_lowercase().as_str() {
"center" => {
if first_child != "center-block" {
return Err(
"Center greater blocks should correspond to a center-block cell.".into(),
);
}
}
"quote" => {
if first_child != "quote-block" {
return Err("Quote greater blocks should correspond to a quote-block cell.".into());
}
}
"center" => "center-block",
"quote" => "quote-block",
_ => todo!(),
}
},
)?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -411,6 +378,7 @@ fn compare_greater_block<'s>(
Ok(DiffResult {
status: this_status,
name: "greater-block".to_owned(),
message: None,
children: child_status,
})
}
@ -421,13 +389,7 @@ fn compare_dynamic_block<'s>(
rust: &'s DynamicBlock<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "dynamic-block" {
return Err("Dynamic block should correspond to a dynamic-block cell.".into());
}
assert_name(emacs, "dynamic-block")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -456,6 +418,7 @@ fn compare_dynamic_block<'s>(
Ok(DiffResult {
status: this_status,
name: "dynamic-block".to_owned(),
message: None,
children: child_status,
})
}
@ -466,13 +429,7 @@ fn compare_footnote_definition<'s>(
rust: &'s FootnoteDefinition<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "footnote-definition" {
return Err("Paragraph should correspond to a paragraph cell.".into());
}
assert_name(emacs, "footnote-definition")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -501,6 +458,7 @@ fn compare_footnote_definition<'s>(
Ok(DiffResult {
status: this_status,
name: "footnote-definition".to_owned(),
message: None,
children: child_status,
})
}
@ -511,13 +469,7 @@ fn compare_comment<'s>(
rust: &'s Comment<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "comment" {
return Err("Comment should correspond to a comment cell.".into());
}
assert_name(emacs, "comment")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -542,6 +494,7 @@ fn compare_comment<'s>(
Ok(DiffResult {
status: this_status,
name: "comment".to_owned(),
message: None,
children: child_status,
})
}
@ -552,13 +505,7 @@ fn compare_drawer<'s>(
rust: &'s Drawer<'s>,
) -> Result<DiffResult, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != "drawer" {
return Err("Drawer should correspond to a drawer cell.".into());
}
assert_name(emacs, "drawer")?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
@ -587,6 +534,7 @@ fn compare_drawer<'s>(
Ok(DiffResult {
status: this_status,
name: "drawer".to_owned(),
message: None,
children: child_status,
})
}

View File

@ -1,5 +1,7 @@
use crate::parser::Source;
use super::sexp::Token;
/// Check if the child string slice is a slice of the parent string slice.
fn is_slice_of(parent: &str, child: &str) -> bool {
let parent_start = parent.as_ptr() as usize;
@ -19,3 +21,19 @@ pub fn get_offsets<'s, S: Source<'s>>(source: &'s str, rust_object: &'s S) -> (u
let end = offset + rust_object_source.len();
(offset, end)
}
pub fn assert_name<'s>(emacs: &'s Token<'s>, name: &str) -> Result<(), Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let first_child = children
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_child != name {
Err(format!(
"Expected a {expected} cell, but found a {found} cell.",
expected = name,
found = first_child
))?;
}
Ok(())
}