Skip to content

Commit 0a63ed6

Browse files
authored
Try #108:
2 parents 09693de + eaa7605 commit 0a63ed6

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-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: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,49 @@
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::*;
38+
39+
let bytes: Vec<u16> = s.encode_wide().collect();
40+
41+
bytes
42+
.split(|v| *v == u16::from(c))
43+
.map(|bytes| OsString::from_wide(bytes))
44+
.collect()
45+
}
46+
747
/// This struct loads external lint crates into memory and provides a safe API
848
/// to call the respective methods on all of them.
949
#[derive(Default)]
@@ -15,17 +55,16 @@ impl<'ast> LintCrateRegistry<'ast> {
1555
/// # Errors
1656
/// This can return errors if the library couldn't be found or if the
1757
/// required symbols weren't provided.
18-
fn load_external_lib(&mut self, lib_path: &str) -> Result<(), LoadingError> {
58+
fn load_external_lib(lib_path: &OsStr) -> Result<LoadedLintCrate<'ast>, LoadingError> {
1959
let lib: &'static Library = Box::leak(Box::new(
2060
unsafe { Library::new(lib_path) }.map_err(|_| LoadingError::FileNotFound)?,
2161
));
2262

2363
let pass = LoadedLintCrate::try_from_lib(lib)?;
2464

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

28-
Ok(())
67+
Ok(pass)
2968
}
3069

3170
/// # Panics
@@ -34,12 +73,21 @@ impl<'ast> LintCrateRegistry<'ast> {
3473
pub fn new_from_env() -> Self {
3574
let mut new_self = Self::default();
3675

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-
}
76+
let Some((_, lint_crates_lst)) = std::env::vars_os().find(|(name, _val)| name == "MARKER_LINT_CRATES") else {
77+
panic!("Adapter tried to find `MARKER_LINT_CRATES` env variable, but it was not present");
78+
};
79+
80+
for lib in split_os_str(&lint_crates_lst, b';') {
81+
if lib.is_empty() {
82+
continue;
4283
}
84+
85+
let lib = match Self::load_external_lib(&lib) {
86+
Ok(v) => v,
87+
Err(err) => panic!("Unable to load `{}`, reason: {err:?}", lib.to_string_lossy()),
88+
};
89+
90+
new_self.passes.push(lib);
4391
}
4492

4593
new_self
@@ -113,7 +161,7 @@ macro_rules! gen_LoadedLintCrate {
113161
}
114162

115163
let set_ast_context = unsafe {
116-
lib.get::<for<'ast> unsafe extern "C" fn(&'ast AstContext<'ast>) -> ()>(b"set_ast_context\0")
164+
lib.get::<for<'ast> unsafe extern "C" fn(&'ast AstContext<'ast>)>(b"set_ast_context\0")
117165
.map_err(|_| LoadingError::MissingLintDeclaration)?
118166
};
119167

@@ -144,7 +192,7 @@ macro_rules! gen_LoadedLintCrate {
144192

145193
// safe wrapper to external functions
146194
$(
147-
fn $fn_name<'ast>(& $($mut_)* self $(, $arg_name: $arg_ty)*) -> $ret_ty {
195+
fn $fn_name<'ast>(&self $(, $arg_name: $arg_ty)*) -> $ret_ty {
148196
unsafe {
149197
(self.$fn_name)($($arg_name,)*)
150198
}

0 commit comments

Comments
 (0)