2023-12-29 15:03:36 -05:00
|
|
|
use serde::Deserialize;
|
2023-12-24 15:26:45 -05:00
|
|
|
use serde::Serialize;
|
|
|
|
|
|
2023-12-24 15:48:33 -05:00
|
|
|
use super::to_wasm::ToWasmContext;
|
|
|
|
|
use super::to_wasm::ToWasmStandardProperties;
|
2023-12-27 11:36:47 -05:00
|
|
|
use crate::types::PostBlank;
|
|
|
|
|
use crate::types::StandardProperties;
|
2023-12-24 15:26:45 -05:00
|
|
|
|
2023-12-29 15:03:36 -05:00
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
2023-12-24 15:26:45 -05:00
|
|
|
pub(crate) struct WasmStandardProperties {
|
2023-12-27 17:07:42 -05:00
|
|
|
pub(crate) begin: usize,
|
|
|
|
|
pub(crate) end: usize,
|
|
|
|
|
pub(crate) contents_begin: Option<usize>,
|
|
|
|
|
pub(crate) contents_end: Option<usize>,
|
|
|
|
|
pub(crate) post_blank: PostBlank,
|
2023-12-24 15:26:45 -05:00
|
|
|
}
|
|
|
|
|
|
2023-12-24 15:48:33 -05:00
|
|
|
impl<'s, SP: StandardProperties<'s>> ToWasmStandardProperties for SP {
|
|
|
|
|
type Output = WasmStandardProperties;
|
|
|
|
|
|
|
|
|
|
fn to_wasm_standard_properties(
|
|
|
|
|
&self,
|
|
|
|
|
wasm_context: ToWasmContext<'_>,
|
|
|
|
|
) -> Result<Self::Output, crate::error::CustomError> {
|
|
|
|
|
let (begin, end) = get_char_indices(wasm_context.full_document, self.get_source());
|
|
|
|
|
let (contents_begin, contents_end) = match self.get_contents() {
|
|
|
|
|
Some(contents) => {
|
|
|
|
|
let (begin, end) = get_char_indices(wasm_context.full_document, contents);
|
|
|
|
|
(Some(begin), Some(end))
|
|
|
|
|
}
|
|
|
|
|
None => (None, None),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let post_blank = self.get_post_blank();
|
|
|
|
|
Ok(WasmStandardProperties {
|
|
|
|
|
begin,
|
|
|
|
|
end,
|
|
|
|
|
contents_begin,
|
|
|
|
|
contents_end,
|
|
|
|
|
post_blank,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_char_indices(original_document: &str, subset: &str) -> (usize, usize) {
|
|
|
|
|
let (begin_byte, end_byte) = get_rust_byte_offsets(original_document, subset);
|
|
|
|
|
// Add 1 to make this 1-based to match emacs.
|
|
|
|
|
let begin_char = original_document[..begin_byte].chars().count() + 1;
|
|
|
|
|
// Also 1-based:
|
|
|
|
|
let end_char = begin_char + original_document[begin_byte..end_byte].chars().count();
|
|
|
|
|
(begin_char, end_char)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get the byte offset into source that the string slice exists at.
|
|
|
|
|
///
|
|
|
|
|
/// These offsets are zero-based.
|
|
|
|
|
fn get_rust_byte_offsets(original_document: &str, subset: &str) -> (usize, usize) {
|
|
|
|
|
debug_assert!(is_slice_of(original_document, subset));
|
|
|
|
|
let offset = subset.as_ptr() as usize - original_document.as_ptr() as usize;
|
|
|
|
|
let end = offset + subset.len();
|
|
|
|
|
(offset, end)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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;
|
|
|
|
|
let parent_end = parent_start + parent.len();
|
|
|
|
|
let child_start = child.as_ptr() as usize;
|
|
|
|
|
let child_end = child_start + child.len();
|
|
|
|
|
child_start >= parent_start && child_end <= parent_end
|
|
|
|
|
}
|