#[cfg(not(target_arch = "wasm32"))]
mod native {
use crate::{
error::{IncludedRangesError, LanguageError, ParserError},
language::Language,
logger::{Logger, LoggerReturn},
point::Point,
range::Range,
tree::Tree,
};
use core::sync::atomic::AtomicUsize;
use std::convert::TryFrom;
pub struct Parser {
inner: tree_sitter::Parser,
}
impl Parser {
#[inline]
pub fn new() -> Result<Self, ParserError> {
let inner = tree_sitter::Parser::new();
Ok(Self { inner })
}
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn cancellation_flag(&self) -> Option<&AtomicUsize> {
self.inner.cancellation_flag()
}
#[inline]
pub fn language(&self) -> Option<Language> {
self.inner.language().map(Into::into)
}
#[inline]
pub fn logger(&self) -> Option<LoggerReturn> {
self.inner.logger().map(LoggerReturn::new)
}
#[inline]
pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Result<Option<Tree>, ParserError> {
let old_tree = old_tree.map(|tree| &tree.inner);
Ok(self.inner.parse(text, old_tree).map(Into::into))
}
#[inline]
pub fn parse_utf16(
&mut self,
text: impl AsRef<[u16]>,
old_tree: Option<&Tree>,
) -> Result<Option<Tree>, ParserError> {
let old_tree = old_tree.map(|tree| &tree.inner);
Ok(self.inner.parse_utf16(text, old_tree).map(Into::into))
}
#[inline]
pub fn parse_utf16_with<T>(
&mut self,
mut callback: impl FnMut(u32, Point) -> T,
old_tree: Option<&Tree>,
) -> Result<Option<Tree>, ParserError>
where
T: AsRef<[u16]>,
{
let mut callback = |offset, inner| callback(u32::try_from(offset).unwrap(), Point { inner });
let old_tree = old_tree.map(|tree| &tree.inner);
Ok(self.inner.parse_utf16_with(&mut callback, old_tree).map(Into::into))
}
#[inline]
pub fn parse_with<T>(
&mut self,
mut callback: impl FnMut(u32, Point) -> T + 'static,
old_tree: Option<&Tree>,
) -> Result<Option<Tree>, ParserError>
where
T: AsRef<[u8]>,
{
let mut callback = |offset, inner| callback(u32::try_from(offset).unwrap(), Point { inner });
let old_tree = old_tree.map(|tree| &tree.inner);
Ok(self.inner.parse_with(&mut callback, old_tree).map(Into::into))
}
#[cfg(unix)]
#[inline]
pub fn print_dot_graphs(&mut self, file: &impl std::os::unix::io::AsRawFd) {
self.inner.print_dot_graphs(file)
}
#[inline]
pub fn reset(&mut self) {
self.inner.reset()
}
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn set_cancellation_flag(&mut self, flag: Option<&AtomicUsize>) {
self.inner.set_cancellation_flag(flag);
}
#[inline]
pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
let ranges = ranges.iter().map(|range| range.inner).collect::<Vec<_>>();
self.inner.set_included_ranges(&ranges).map_err(Into::into)
}
#[inline]
pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
let language = language.inner;
self.inner.set_language(language).map_err(Into::into)
}
#[inline]
pub fn set_logger(&mut self, logger: Option<Logger<'static>>) {
self.inner.set_logger(logger)
}
#[inline]
pub fn set_timeout_micros(&mut self, timeout_micros: f64) {
self.inner.set_timeout_micros(timeout_micros as u64)
}
#[inline]
pub fn stop_printing_dot_graphs(&mut self) {
self.inner.stop_printing_dot_graphs()
}
#[inline]
pub fn timeout_micros(&self) -> f64 {
self.inner.timeout_micros() as f64
}
}
impl From<tree_sitter::Parser> for Parser {
#[inline]
fn from(inner: tree_sitter::Parser) -> Self {
Self { inner }
}
}
impl std::panic::RefUnwindSafe for Parser {
}
unsafe impl Send for Parser {
}
impl Unpin for Parser {
}
impl std::panic::UnwindSafe for Parser {
}
}
#[cfg(not(target_arch = "wasm32"))]
pub use native::*;
#[cfg(target_arch = "wasm32")]
mod wasm {
use crate::{
error::{IncludedRangesError, LanguageError, ParserError},
language::Language,
logger::{LogType, Logger, LoggerReturn},
point::Point,
range::Range,
tree::Tree,
};
use js_sys::{Function, JsString};
use wasm_bindgen::{prelude::*, JsCast};
pub struct Parser {
inner: web_tree_sitter::Parser,
options: web_tree_sitter::ParseOptions,
}
unsafe impl Send for Parser {
}
impl Parser {
#[inline]
pub fn new() -> Result<Self, ParserError> {
let inner = web_tree_sitter::Parser::new()?;
let options = Default::default();
Ok(Self { inner, options })
}
#[inline]
pub fn language(&self) -> Option<Language> {
self.inner.get_language().map(Into::into)
}
#[inline]
pub fn logger(&self) -> Option<LoggerReturn> {
if let Some(logger) = self.inner.get_logger() {
let options = js_sys::Object::new().into();
let fun = Box::new(move |type_: LogType, message: JsString| {
let context = &wasm_bindgen::JsValue::NULL;
let arg0 = &type_.into();
let arg1 = &options;
let arg2 = &message.into();
logger.call3(context, arg0, arg1, arg2).unwrap();
}) as Box<dyn FnMut(LogType, JsString)>;
Some(LoggerReturn::new(fun))
} else {
None
}
}
#[inline]
pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Result<Option<Tree>, ParserError> {
let text = text.as_ref();
let text = unsafe { std::str::from_utf8_unchecked(text) };
let text = &text.into();
let old_tree = old_tree.map(|tree| &tree.inner);
let options = Some(&self.options);
self.inner
.parse_with_string(text, old_tree, options)
.map(|ok| ok.map(Into::into))
.map_err(Into::into)
}
#[inline]
pub fn parse_with<T>(
&mut self,
mut callback: impl FnMut(u32, Option<Point>, Option<u32>) -> T + 'static,
old_tree: Option<&Tree>,
) -> Result<Option<Tree>, ParserError>
where
T: AsRef<[u8]>,
{
let closure = Closure::wrap(Box::new(move |start_index, start_point: Option<_>, end_index| {
let start_point = start_point.map(Into::into);
let result = callback(start_index, start_point, end_index);
let result = result.as_ref();
let result = unsafe { std::str::from_utf8_unchecked(result) };
Some(result.into())
})
as Box<dyn FnMut(u32, Option<web_tree_sitter::Point>, Option<u32>) -> Option<JsString>>);
let input = closure.as_ref().unchecked_ref();
let old_tree = old_tree.map(|tree| &tree.inner);
let options = Some(&self.options);
let result = self
.inner
.parse_with_function(input, old_tree, options)
.map(|ok| ok.map(Into::into))
.map_err(Into::into);
closure.forget();
result
}
#[inline]
pub fn reset(&mut self) {
self.inner.reset()
}
#[inline]
pub fn set_included_ranges<'a>(&mut self, ranges: &'a [Range]) -> Result<(), IncludedRangesError> {
let ranges = ranges.iter().map(|range| &range.inner).collect::<js_sys::Array>();
let options = web_tree_sitter::ParseOptions::new(Some(&ranges));
self.options = options;
Ok(())
}
#[inline]
pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
let language = Some(&language.inner);
self.inner.set_language(language).map_err(Into::into)
}
#[inline]
pub fn set_logger(&mut self, logger: Option<Logger<'static>>) {
if let Some(logger) = logger {
let clo = Closure::wrap(logger);
let fun = clo.as_ref().unchecked_ref::<Function>();
self.inner.set_logger(Some(&fun));
clo.forget();
} else {
self.inner.set_logger(None);
}
}
#[inline]
pub fn set_timeout_micros(&mut self, timeout_micros: f64) {
self.inner.set_timeout_micros(timeout_micros)
}
#[inline]
pub fn timeout_micros(&self) -> f64 {
self.inner.get_timeout_micros()
}
}
impl Drop for Parser {
#[inline]
fn drop(&mut self) {
self.inner.delete();
}
}
impl From<web_tree_sitter::Parser> for Parser {
#[inline]
fn from(inner: web_tree_sitter::Parser) -> Self {
let options = Default::default();
Self { inner, options }
}
}
impl std::panic::RefUnwindSafe for Parser {
}
impl Unpin for Parser {
}
impl std::panic::UnwindSafe for Parser {
}
}
#[cfg(target_arch = "wasm32")]
pub use wasm::*;