Files
organic/src/wasm/standard_properties.rs

72 lines
2.5 KiB
Rust
Raw Normal View History

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;
use crate::types::PostBlank;
use crate::types::StandardProperties;
2023-12-24 15:26:45 -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
}