Skip to content

Commit bf86f4a

Browse files
authored
Try #108:
2 parents 09693de + 75154d3 commit bf86f4a

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

Cargo.lock

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

marker_adapter/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ license = "MIT OR Apache-2.0"
1010
marker_api = { path = "../marker_api" }
1111

1212
libloading = "0.7.3"
13+
cfg-if = "1.0.0"

marker_adapter/src/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use marker_api::{
1414
/// change and calling functions on them would require a stable ABI which Rust
1515
/// doesn't provide.
1616
///
17-
/// In this case, the `DriverContextWrapper` will be passed as a `*const ()`
17+
/// In this case, the [`DriverContextWrapper`] will be passed as a `*const ()`
1818
/// pointer to [`DriverCallbacks`] which will do nothing with this data other
1919
/// than giving it back to functions declared in this module. Since the `&dyn`
2020
/// object is created, only used here and everything is compiled during the same

marker_adapter/src/loader.rs

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,46 @@
1+
use cfg_if::cfg_if;
12
use libloading::Library;
23

34
use marker_api::context::AstContext;
45
use marker_api::lint::Lint;
56
use marker_api::LintPass;
67

8+
use std::ffi::{OsStr, OsString};
9+
10+
/// Splits [`OsStr`] by an ascii character
11+
fn split_os_str(s: &OsStr, c: u8) -> Vec<OsString> {
12+
cfg_if! {
13+
if #[cfg(unix)] {
14+
unix_split_os_str(s, c)
15+
} else if #[cfg(windows)] {
16+
windows_split_os_str(s, c)
17+
} else {
18+
unimplemented!("`split_os_str` currently works only on unix and windows")
19+
}
20+
}
21+
}
22+
23+
#[cfg(unix)]
24+
#[doc(hidden)]
25+
fn unix_split_os_str(s: &OsStr, c: u8) -> Vec<OsString> {
26+
use std::os::unix::ffi::OsStrExt;
27+
28+
s.as_bytes()
29+
.split(|byte| *byte == c)
30+
.map(|bytes| OsStr::from_bytes(bytes).into())
31+
.collect()
32+
}
33+
34+
#[cfg(windows)]
35+
#[doc(hidden)]
36+
fn windows_split_os_str(s: &OsStr, c: u8) -> Vec<OsString> {
37+
use std::os::windows::ffi::{OsStrExt, OsStringExt};
38+
39+
let bytes: Vec<u16> = s.encode_wide().collect();
40+
41+
bytes.split(|v| *v == u16::from(c)).map(OsString::from_wide).collect()
42+
}
43+
744
/// This struct loads external lint crates into memory and provides a safe API
845
/// to call the respective methods on all of them.
946
#[derive(Default)]
@@ -15,17 +52,16 @@ impl<'ast> LintCrateRegistry<'ast> {
1552
/// # Errors
1653
/// This can return errors if the library couldn't be found or if the
1754
/// required symbols weren't provided.
18-
fn load_external_lib(&mut self, lib_path: &str) -> Result<(), LoadingError> {
55+
fn load_external_lib(lib_path: &OsStr) -> Result<LoadedLintCrate<'ast>, LoadingError> {
1956
let lib: &'static Library = Box::leak(Box::new(
2057
unsafe { Library::new(lib_path) }.map_err(|_| LoadingError::FileNotFound)?,
2158
));
2259

2360
let pass = LoadedLintCrate::try_from_lib(lib)?;
2461

25-
self.passes.push(pass);
2662
// FIXME: Create issue for lifetimes and fix droping and pointer decl stuff
2763

28-
Ok(())
64+
Ok(pass)
2965
}
3066

3167
/// # Panics
@@ -34,12 +70,21 @@ impl<'ast> LintCrateRegistry<'ast> {
3470
pub fn new_from_env() -> Self {
3571
let mut new_self = Self::default();
3672

37-
if let Ok(lint_crates_lst) = std::env::var("MARKER_LINT_CRATES") {
38-
for lint_crate in lint_crates_lst.split(';') {
39-
if let Err(err) = new_self.load_external_lib(lint_crate) {
40-
panic!("Unable to load `{lint_crate}`, reason: {err:?}");
41-
}
73+
let Some((_, lint_crates_lst)) = std::env::vars_os().find(|(name, _val)| name == "MARKER_LINT_CRATES") else {
74+
panic!("Adapter tried to find `MARKER_LINT_CRATES` env variable, but it was not present");
75+
};
76+
77+
for lib in split_os_str(&lint_crates_lst, b';') {
78+
if lib.is_empty() {
79+
continue;
4280
}
81+
82+
let lib = match Self::load_external_lib(&lib) {
83+
Ok(v) => v,
84+
Err(err) => panic!("Unable to load `{}`, reason: {err:?}", lib.to_string_lossy()),
85+
};
86+
87+
new_self.passes.push(lib);
4388
}
4489

4590
new_self
@@ -113,7 +158,7 @@ macro_rules! gen_LoadedLintCrate {
113158
}
114159

115160
let set_ast_context = unsafe {
116-
lib.get::<for<'ast> unsafe extern "C" fn(&'ast AstContext<'ast>) -> ()>(b"set_ast_context\0")
161+
lib.get::<for<'ast> unsafe extern "C" fn(&'ast AstContext<'ast>)>(b"set_ast_context\0")
117162
.map_err(|_| LoadingError::MissingLintDeclaration)?
118163
};
119164

@@ -144,7 +189,7 @@ macro_rules! gen_LoadedLintCrate {
144189

145190
// safe wrapper to external functions
146191
$(
147-
fn $fn_name<'ast>(& $($mut_)* self $(, $arg_name: $arg_ty)*) -> $ret_ty {
192+
fn $fn_name<'ast>(&self $(, $arg_name: $arg_ty)*) -> $ret_ty {
148193
unsafe {
149194
(self.$fn_name)($($arg_name,)*)
150195
}

0 commit comments

Comments
 (0)