Skip to content

Commit 7e80e47

Browse files
committed
chore: finish bindings
1 parent 18447da commit 7e80e47

File tree

8 files changed

+6814
-11
lines changed

8 files changed

+6814
-11
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
/target
22
**/*.rs.bk
33
Cargo.lock
4+
*.pyc
5+
build
6+
*.so

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ crate-type = ["cdylib"]
1010
[dependencies]
1111
pyo3 = { version="0.4", features=["extension-module"] }
1212
source-map-mappings = { version="0.5" }
13+
serde = "1.0"
14+
serde_derive = "1.0"
15+
serde_json = "1.0"

py_sourcemap/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .py_sourcemap import SourcemapParser
2+
3+
__all__ = ["SourcemapParser"]

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
setuptools-rust==0.10.2

setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from setuptools import setup
2+
from setuptools_rust import Binding, RustExtension
3+
4+
setup(name='py-sourcemap',
5+
version='0.1',
6+
rust_extensions=[RustExtension('py_sourcemap.py_sourcemap',
7+
'Cargo.toml', binding=Binding.PyO3)],
8+
packages=['py_sourcemap'],
9+
# rust extensions are not zip safe, just like C-extensions.
10+
zip_safe=False
11+
)

src/lib.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,66 @@
22

33
extern crate pyo3;
44
extern crate source_map_mappings;
5+
#[macro_use] extern crate serde_derive;
6+
extern crate serde;
7+
extern crate serde_json;
58

69
use std::fs::File;
7-
use std::io::{BufReader, Read};
810

911
use pyo3::prelude::*;
10-
use source_map_mappings::{Bias, Mappings, parse_mappings};
12+
use source_map_mappings::{Bias, Mapping, Mappings, parse_mappings};
13+
14+
#[derive(Serialize, Deserialize, Debug)]
15+
#[serde(rename_all = "camelCase")]
16+
struct RawSourceMap {
17+
version: u8,
18+
sources: Vec<String>,
19+
names: Vec<String>,
20+
mappings: String,
21+
file: String,
22+
source_root: Option<String>,
23+
}
1124

1225
#[pyclass]
1326
struct SourcemapParser {
14-
parsed_map: Mappings<()>
27+
parsed_map: Mappings<()>,
28+
sources: Vec<String>,
29+
names: Vec<String>,
1530
}
1631

1732
#[pymethods]
1833
impl SourcemapParser {
1934
#[new]
2035
fn __new__(obj: &PyRawObject, path: &str) -> PyResult<()> {
2136
let file = File::open(path).map_err(PyErr::from)?;
22-
let mut buffers = vec![];
23-
let mut reader = BufReader::new(file);
24-
reader.read_to_end(&mut buffers).map_err(PyErr::from)?;
25-
let mappings = parse_mappings(&buffers).map_err(|_| PyErr::new::<exc::TypeError, _>(format!("Parse Sourcemap failed: {}", path)))?;
26-
obj.init(|_| SourcemapParser {
37+
let raw_sourcemap: RawSourceMap = serde_json::from_reader(file).map_err(|e| {
38+
PyErr::new::<exc::TypeError, _>(format!("{:?}", e))
39+
})?;
40+
let mapping_bytes = raw_sourcemap.mappings.as_bytes();
41+
let mappings = parse_mappings(mapping_bytes).map_err(|_| {
42+
PyErr::new::<exc::TypeError, _>(format!("Parse Sourcemap failed: {}", path))
43+
})?;
44+
let sources = raw_sourcemap.sources;
45+
let names = raw_sourcemap.names;
46+
obj.init(move |_| SourcemapParser {
2747
parsed_map: mappings,
48+
sources,
49+
names,
2850
})
2951
}
3052

31-
fn original_location_for(&self, generated_line: u32, generated_column: u32) -> PyResult<(u32, u32)> {
32-
if let Some(mapping) = self.parsed_map.original_location_for(generated_line, generated_column, Bias::LeastUpperBound) {
33-
return Ok((mapping.generated_line, mapping.generated_column))
53+
fn original_location_for(&self, generated_line: u32, generated_column: u32) -> PyResult<(u32, u32, Option<String>, Option<String>)> {
54+
if let Some(Mapping { original, .. }) = self.parsed_map.original_location_for(generated_line, generated_column, Bias::LeastUpperBound) {
55+
match original {
56+
Some(location) => {
57+
let name = location.name.and_then(|index| {
58+
self.names.get(index as usize).map(|str_slice| str_slice.to_string())
59+
});
60+
let source = self.sources.get(location.source as usize).map(|str_slice| str_slice.to_string());
61+
return Ok((location.original_line, location.original_column, source, name))
62+
},
63+
None => return Err(PyErr::new::<exc::TypeError, _>("No original lines"))
64+
};
3465
}
3566
Err(PyErr::new::<exc::TypeError, _>("No sources found"))
3667
}

tests/index.js.map

Lines changed: 6744 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/lookup.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from py_sourcemap import SourcemapParser
2+
3+
sourcemap = SourcemapParser("./tests/index.js.map")
4+
5+
result = sourcemap.original_location_for(0, 195302)
6+
7+
print(result)

0 commit comments

Comments
 (0)