#![deny(missing_docs)]
extern crate source_map_mappings;
use source_map_mappings::{Bias, Error, Mapping, Mappings};
use std::mem;
use std::ptr;
use std::process;
use std::slice;
#[cfg(feature = "profiling")]
mod observer {
use source_map_mappings;
macro_rules! define_raii_observer {
( $name:ident , $ctor:ident , $dtor:ident ) => {
#[derive(Debug)]
pub struct $name;
impl Default for $name {
#[inline]
fn default() -> $name {
extern "C" {
fn $ctor();
}
unsafe {
$ctor();
}
$name
}
}
impl Drop for $name {
#[inline]
fn drop(&mut self) {
extern "C" {
fn $dtor();
}
unsafe {
$dtor();
}
}
}
}
}
define_raii_observer!(ParseMappings, start_parse_mappings, end_parse_mappings);
define_raii_observer!(
SortByOriginalLocation,
start_sort_by_original_location,
end_sort_by_original_location
);
define_raii_observer!(
SortByGeneratedLocation,
start_sort_by_generated_location,
end_sort_by_generated_location
);
define_raii_observer!(
ComputeColumnSpans,
start_compute_column_spans,
end_compute_column_spans
);
define_raii_observer!(
OriginalLocationFor,
start_original_location_for,
end_original_location_for
);
define_raii_observer!(
GeneratedLocationFor,
start_generated_location_for,
end_generated_location_for
);
define_raii_observer!(
AllGeneratedLocationsFor,
start_all_generated_locations_for,
end_all_generated_locations_for
);
#[derive(Debug, Default)]
pub struct Observer;
impl source_map_mappings::Observer for Observer {
type ParseMappings = ParseMappings;
type SortByOriginalLocation = SortByOriginalLocation;
type SortByGeneratedLocation = SortByGeneratedLocation;
type ComputeColumnSpans = ComputeColumnSpans;
type OriginalLocationFor = OriginalLocationFor;
type GeneratedLocationFor = GeneratedLocationFor;
type AllGeneratedLocationsFor = AllGeneratedLocationsFor;
}
}
#[cfg(not(feature = "profiling"))]
mod observer {
pub type Observer = ();
}
use observer::Observer;
static mut LAST_ERROR: Option<Error> = None;
#[no_mangle]
pub extern "C" fn get_last_error() -> u32 {
unsafe {
match LAST_ERROR {
None => 0,
Some(e) => e as u32,
}
}
}
#[inline]
fn assert_pointer_is_word_aligned(p: *mut u8) {
debug_assert_eq!(p as usize & (mem::size_of::<usize>() - 1), 0);
}
#[no_mangle]
pub extern "C" fn allocate_mappings(size: usize) -> *mut u8 {
let size_in_units_of_usize = (size + mem::size_of::<usize>() - 1) / mem::size_of::<usize>();
let mut vec: Vec<usize> = Vec::with_capacity(size_in_units_of_usize + 2);
let capacity = vec.capacity();
vec.push(capacity);
vec.push(size);
let ptr = vec.as_mut_ptr();
debug_assert!(!ptr.is_null());
mem::forget(vec);
let ptr = ptr.wrapping_offset(2) as *mut u8;
assert_pointer_is_word_aligned(ptr);
ptr
}
#[inline]
fn constrain<'a, T>(_scope: &'a (), reference: &'a T) -> &'a T
where
T: ?Sized,
{
reference
}
#[no_mangle]
pub extern "C" fn parse_mappings(mappings: *mut u8) -> *mut Mappings<Observer> {
assert_pointer_is_word_aligned(mappings);
let mappings = mappings as *mut usize;
let capacity_ptr = mappings.wrapping_offset(-2);
debug_assert!(!capacity_ptr.is_null());
let capacity = unsafe { *capacity_ptr };
let size_ptr = mappings.wrapping_offset(-1);
debug_assert!(!size_ptr.is_null());
let size = unsafe { *size_ptr };
let result = unsafe {
let input = slice::from_raw_parts(mappings as *const u8, size);
let this_scope = ();
let input = constrain(&this_scope, input);
source_map_mappings::parse_mappings(input)
};
let size_in_usizes = (size + mem::size_of::<usize>() - 1) / mem::size_of::<usize>();
unsafe {
Vec::<usize>::from_raw_parts(capacity_ptr, size_in_usizes + 2, capacity);
}
match result {
Ok(mappings) => Box::into_raw(Box::new(mappings)),
Err(e) => {
unsafe {
LAST_ERROR = Some(e);
}
ptr::null_mut()
}
}
}
#[no_mangle]
pub extern "C" fn free_mappings(mappings: *mut Mappings<Observer>) {
unsafe {
Box::from_raw(mappings);
}
}
#[inline]
unsafe fn mappings_mut<'a>(
_scope: &'a (),
mappings: *mut Mappings<Observer>,
) -> &'a mut Mappings<Observer> {
mappings.as_mut().unwrap()
}
extern "C" {
fn mapping_callback(
generated_line: u32,
generated_column: u32,
has_last_generated_column: bool,
last_generated_column: u32,
has_original: bool,
source: u32,
original_line: u32,
original_column: u32,
has_name: bool,
name: u32,
);
}
#[inline]
unsafe fn invoke_mapping_callback(mapping: &Mapping) {
let generated_line = mapping.generated_line;
let generated_column = mapping.generated_column;
let (has_last_generated_column, last_generated_column) =
if let Some(last_generated_column) = mapping.last_generated_column {
(true, last_generated_column)
} else {
(false, 0)
};
let (has_original, source, original_line, original_column, has_name, name) =
if let Some(original) = mapping.original.as_ref() {
let (has_name, name) = if let Some(name) = original.name {
(true, name)
} else {
(false, 0)
};
(
true,
original.source,
original.original_line,
original.original_column,
has_name,
name,
)
} else {
(false, 0, 0, 0, false, 0)
};
mapping_callback(
generated_line,
generated_column,
has_last_generated_column,
last_generated_column,
has_original,
source,
original_line,
original_column,
has_name,
name,
);
}
#[no_mangle]
pub extern "C" fn by_generated_location(mappings: *mut Mappings<Observer>) {
let this_scope = ();
let mappings = unsafe { mappings_mut(&this_scope, mappings) };
mappings
.by_generated_location()
.iter()
.for_each(|m| unsafe {
invoke_mapping_callback(m);
});
}
#[no_mangle]
pub extern "C" fn compute_column_spans(mappings: *mut Mappings<Observer>) {
let this_scope = ();
let mappings = unsafe { mappings_mut(&this_scope, mappings) };
mappings.compute_column_spans();
}
#[no_mangle]
pub extern "C" fn by_original_location(mappings: *mut Mappings<Observer>) {
let this_scope = ();
let mappings = unsafe { mappings_mut(&this_scope, mappings) };
mappings.by_original_location().for_each(|m| unsafe {
invoke_mapping_callback(m);
});
}
#[inline]
fn u32_to_bias(bias: u32) -> Bias {
match bias {
1 => Bias::GreatestLowerBound,
2 => Bias::LeastUpperBound,
otherwise => if cfg!(debug_assertions) {
panic!(
"Invalid `Bias = {}`; must be `Bias::GreatestLowerBound = {}` or \
`Bias::LeastUpperBound = {}`",
otherwise,
Bias::GreatestLowerBound as u32,
Bias::LeastUpperBound as u32,
)
} else {
process::abort()
},
}
}
#[no_mangle]
pub extern "C" fn original_location_for(
mappings: *mut Mappings<Observer>,
generated_line: u32,
generated_column: u32,
bias: u32,
) {
let this_scope = ();
let mappings = unsafe { mappings_mut(&this_scope, mappings) };
let bias = u32_to_bias(bias);
if let Some(m) = mappings.original_location_for(generated_line, generated_column, bias) {
unsafe {
invoke_mapping_callback(m);
}
}
}
#[no_mangle]
pub extern "C" fn generated_location_for(
mappings: *mut Mappings<Observer>,
source: u32,
original_line: u32,
original_column: u32,
bias: u32,
) {
let this_scope = ();
let mappings = unsafe { mappings_mut(&this_scope, mappings) };
let bias = u32_to_bias(bias);
if let Some(m) = mappings.generated_location_for(source, original_line, original_column, bias) {
unsafe {
invoke_mapping_callback(m);
}
}
}
#[no_mangle]
pub extern "C" fn all_generated_locations_for(
mappings: *mut Mappings<Observer>,
source: u32,
original_line: u32,
has_original_column: bool,
original_column: u32,
) {
let this_scope = ();
let mappings = unsafe { mappings_mut(&this_scope, mappings) };
let original_column = if has_original_column {
Some(original_column)
} else {
None
};
for m in mappings.all_generated_locations_for(source, original_line, original_column) {
unsafe {
invoke_mapping_callback(m);
}
}
}