From 3dd7d1620e447957adcb8a5d0b7d9b28e86a15e7 Mon Sep 17 00:00:00 2001 From: amrbashir Date: Mon, 29 Apr 2024 21:26:42 +0300 Subject: [PATCH] fix clippy and update CI --- .github/workflows/audit.yml | 5 +- .github/workflows/change-status-on-pr.yml | 2 +- .github/workflows/clippy-fmt.yml | 30 ++------- .../workflows/covector-version-or-publish.yml | 9 +-- .github/workflows/test.yml | 4 +- crates/nsis-fn/src/lib.rs | 5 +- crates/nsis-plugin-api/src/lib.rs | 67 ++++++++++++++----- crates/nsis-process/src/lib.rs | 24 +++---- crates/nsis-semvercompare/src/lib.rs | 6 +- crates/nsis-tauri-utils/build.rs | 30 ++++++--- 10 files changed, 104 insertions(+), 78 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 184b5af..d2531d1 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -27,8 +27,7 @@ jobs: audit: runs-on: windows-latest steps: - - uses: actions/checkout@v2 - - name: rust audit - uses: actions-rs/audit-check@v1 + - uses: actions/checkout@v4 + - uses: rustsec/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/change-status-on-pr.yml b/.github/workflows/change-status-on-pr.yml index 44f842c..e0d84df 100644 --- a/.github/workflows/change-status-on-pr.yml +++ b/.github/workflows/change-status-on-pr.yml @@ -10,7 +10,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: covector status diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index c72d413..377629d 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -18,33 +18,17 @@ jobs: clippy: runs-on: windows-latest steps: - - uses: actions/checkout@v3 - - name: install stable - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true components: clippy + - run: cargo clippy --release --all-targets --all-features -- -D warnings - - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --all-targets --all-features -- -D warnings - - fmt: + rustfmt: runs-on: windows-latest steps: - - uses: actions/checkout@v3 - - name: install stable - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true components: rustfmt - - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check \ No newline at end of file + - run: cargo fmt --all -- --check \ No newline at end of file diff --git a/.github/workflows/covector-version-or-publish.yml b/.github/workflows/covector-version-or-publish.yml index b301a21..a0cce04 100644 --- a/.github/workflows/covector-version-or-publish.yml +++ b/.github/workflows/covector-version-or-publish.yml @@ -19,16 +19,11 @@ jobs: successfulPublish: ${{ steps.covector.outputs.successfulPublish }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Setup node - uses: actions/setup-node@v3 - with: - node-version: 16 - check-latest: true - registry-url: 'https://registry.npmjs.org' + - uses: actions/setup-node@v4 - name: git config run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55cbb3e..e18f0ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: install stable uses: actions-rs/toolchain@v1 @@ -33,4 +33,4 @@ jobs: - uses: actions-rs/cargo@v1 with: - command: test \ No newline at end of file + command: test --release \ No newline at end of file diff --git a/crates/nsis-fn/src/lib.rs b/crates/nsis-fn/src/lib.rs index d6a4bb5..885fb27 100644 --- a/crates/nsis-fn/src/lib.rs +++ b/crates/nsis-fn/src/lib.rs @@ -14,6 +14,9 @@ impl Parse for NsisFn { } } +/// Generates a wrapper NSIS compliant dll export that calls `nsis_plugin_api::exdll_init` +/// automatically. This macro expects the function to return a `Result<(), nsis_plugin_api::Error>` +/// and will automatically push the error to NSIS stack on failure. #[proc_macro_attribute] pub fn nsis_fn(_attr: TokenStream, tokens: TokenStream) -> TokenStream { let tokens = parse_macro_input!(tokens as NsisFn); @@ -23,7 +26,7 @@ pub fn nsis_fn(_attr: TokenStream, tokens: TokenStream) -> TokenStream { let block = func.block; let attrs = func.attrs; - let new_ident = Ident::new(&format!("__{}", ident.to_string()), Span::call_site()); + let new_ident = Ident::new(&format!("__{}", ident), Span::call_site()); quote! { #[inline(always)] diff --git a/crates/nsis-plugin-api/src/lib.rs b/crates/nsis-plugin-api/src/lib.rs index e1c3305..3f70612 100644 --- a/crates/nsis-plugin-api/src/lib.rs +++ b/crates/nsis-plugin-api/src/lib.rs @@ -41,6 +41,11 @@ pub static mut G_STRINGSIZE: c_int = 0; pub static mut G_VARIABLES: *mut wchar_t = core::ptr::null_mut(); pub static mut G_STACKTOP: *mut *mut stack_t = core::ptr::null_mut(); +/// Initis the global variables used by NSIS functions: [`push`], [`pushstr`], [`pushint`], [`pop`], [`popstr`] and [`popint`] +/// +/// # Safety +/// +/// This function mutates static variables and should only be called in a function #[inline(always)] pub unsafe fn exdll_init(string_size: c_int, variables: *mut wchar_t, stacktop: *mut *mut stack_t) { G_STRINGSIZE = string_size; @@ -48,9 +53,9 @@ pub unsafe fn exdll_init(string_size: c_int, variables: *mut wchar_t, stacktop: G_STACKTOP = stacktop; } -pub const ONE: [u16; 2] = [49, 0]; -pub const ZERO: [u16; 2] = [48, 0]; -pub const NEGATIVE_ONE: [u16; 3] = [45, 49, 0]; +pub const ONE: &[u16; 2] = &[49, 0]; +pub const ZERO: &[u16; 2] = &[48, 0]; +pub const NEGATIVE_ONE: &[u16; 3] = &[45, 49, 0]; #[derive(Debug)] pub enum Error { @@ -66,10 +71,15 @@ impl Error { } } pub fn push_err(&self) { - let _ = unsafe { pushstr(&self.description()) }; + let _ = unsafe { pushstr(self.description()) }; } } +/// Pushes some bytes onto the NSIS stack. +/// +/// # Safety +/// +/// This function reads static variables and should only be called after [`exdll_init`] is called. pub unsafe fn push(bytes: &[u16]) -> Result<(), Error> { if G_STACKTOP.is_null() { return Err(Error::StackIsNull); @@ -84,16 +94,31 @@ pub unsafe fn push(bytes: &[u16]) -> Result<(), Error> { Ok(()) } +/// Pushes a string onto the NSIS stack. +/// +/// # Safety +/// +/// This function reads static variables and should only be called after [`exdll_init`] is called. pub unsafe fn pushstr(str: &str) -> Result<(), Error> { - let bytes = encode_wide(str); + let bytes = encode_utf16(str); push(&bytes) } +/// Pushes an integer onto the NSIS stack. +/// +/// # Safety +/// +/// This function reads static variables and should only be called after [`exdll_init`] is called. pub unsafe fn pushint(int: i32) -> Result<(), Error> { let str = int.to_string(); pushstr(&str) } +/// Pops bytes from NSIS stack. +/// +/// # Safety +/// +/// This function reads static variables and should only be called after [`exdll_init`] is called. pub unsafe fn pop() -> Result, Error> { if G_STACKTOP.is_null() || (*G_STACKTOP).is_null() { return Err(Error::StackIsNull); @@ -109,28 +134,38 @@ pub unsafe fn pop() -> Result, Error> { Ok(out) } +/// Pops a string from NSIS stack. +/// +/// # Safety +/// +/// This function reads static variables and should only be called after [`exdll_init`] is called. pub unsafe fn popstr() -> Result { let bytes = pop()?; - Ok(decode_wide(&bytes)) + Ok(decode_utf16_lossy(&bytes)) } +/// Pops an integer from NSIS stack. +/// +/// # Safety +/// +/// This function reads static variables and should only be called after [`exdll_init`] is called. pub unsafe fn popint() -> Result { let str = popstr()?; str.parse().map_err(|_| Error::ParseIntError) } -pub fn encode_wide(str: &str) -> Vec { +pub fn encode_utf16(str: &str) -> Vec { str.encode_utf16() .chain(iter::once(0)) .collect::>() } -pub fn decode_wide(bytes: &[u16]) -> String { +pub fn decode_utf16_lossy(bytes: &[u16]) -> String { let bytes = bytes .iter() .position(|c| *c == 0) .map(|nul| &bytes[..nul]) - .unwrap_or(&bytes); + .unwrap_or(bytes); String::from_utf16_lossy(bytes) } @@ -183,21 +218,21 @@ macro_rules! nsis_plugin { } #[no_mangle] - pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { + pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: isize) -> *mut u8 { let mut i = 0; while i < n { - *dest.offset(i as isize) = *src.offset(i as isize); + *dest.offset(i) = *src.offset(i); i += 1; } return dest; } #[no_mangle] - pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: isize) -> i32 { let mut i = 0; while i < n { - let a = *s1.offset(i as isize); - let b = *s2.offset(i as isize); + let a = *s1.offset(i); + let b = *s2.offset(i); if a != b { return a as i32 - b as i32; } @@ -207,10 +242,10 @@ macro_rules! nsis_plugin { } #[no_mangle] - pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 { + pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: isize) -> *mut u8 { let mut i = 0; while i < n { - *s.offset(i as isize) = c as u8; + *s.offset(i) = c as u8; i += 1; } return s; diff --git a/crates/nsis-process/src/lib.rs b/crates/nsis-process/src/lib.rs index 2a945ef..3fd6250 100644 --- a/crates/nsis-process/src/lib.rs +++ b/crates/nsis-process/src/lib.rs @@ -34,9 +34,9 @@ fn FindProcess() -> Result<(), Error> { let name = popstr()?; if !get_processes(&name).is_empty() { - push(&ZERO) + push(ZERO) } else { - push(&ONE) + push(ONE) } } @@ -56,15 +56,15 @@ fn FindProcessCurrentUser() -> Result<(), Error> { .into_iter() .any(|pid| belongs_to_user(user_sid, pid)) { - push(&ZERO) + push(ZERO) } else { - push(&ONE) + push(ONE) } // Fall back to perMachine checks if we can't get current user id } else if processes.is_empty() { - push(&ONE) + push(ONE) } else { - push(&ZERO) + push(ZERO) } } @@ -80,9 +80,9 @@ fn KillProcess() -> Result<(), Error> { let processes = get_processes(&name); if !processes.is_empty() && processes.into_iter().map(kill).all(|b| b) { - push(&ZERO) + push(ZERO) } else { - push(&ONE) + push(ONE) } } @@ -98,7 +98,7 @@ fn KillProcessCurrentUser() -> Result<(), Error> { let processes = get_processes(&name); if processes.is_empty() { - return push(&ONE); + return push(ONE); } let success = if let Some(user_sid) = get_sid(GetCurrentProcessId()) { @@ -112,9 +112,9 @@ fn KillProcessCurrentUser() -> Result<(), Error> { }; if success { - push(&ZERO) + push(ZERO) } else { - push(&ONE) + push(ONE) } } @@ -196,7 +196,7 @@ fn get_processes(name: &str) -> Vec { if Process32FirstW(handle, &mut process) != 0 { while Process32NextW(handle, &mut process) != 0 { if current_pid != process.th32ProcessID - && decode_wide(&process.szExeFile).to_lowercase() == name.to_lowercase() + && decode_utf16_lossy(&process.szExeFile).to_lowercase() == name.to_lowercase() { processes.push(process.th32ProcessID); } diff --git a/crates/nsis-semvercompare/src/lib.rs b/crates/nsis-semvercompare/src/lib.rs index 885b3a6..d8bca47 100644 --- a/crates/nsis-semvercompare/src/lib.rs +++ b/crates/nsis-semvercompare/src/lib.rs @@ -20,9 +20,9 @@ fn SemverCompare() -> Result<(), Error> { let v2 = popstr()?; match compare(&v1, &v2) { - -1 => push(&NEGATIVE_ONE)?, - 0 => push(&ZERO)?, - 1 => push(&ONE)?, + -1 => push(NEGATIVE_ONE)?, + 0 => push(ZERO)?, + 1 => push(ONE)?, _ => unreachable!(), } diff --git a/crates/nsis-tauri-utils/build.rs b/crates/nsis-tauri-utils/build.rs index cb35723..8243482 100644 --- a/crates/nsis-tauri-utils/build.rs +++ b/crates/nsis-tauri-utils/build.rs @@ -1,9 +1,14 @@ fn main() { - write_plugins(); + combine_plugins_and_write_to_out_dir(); println!("cargo::rustc-link-arg=/ENTRY:DllMain") } -fn write_plugins() { +/// Combines the plugins into one file that is included in lib.rs +/// using `include!(concat!(env!("OUT_DIR"), "/combined_libs.rs"));` +/// +/// Plugins are combined this way because it saves a few kilobytes in the generated DLL +/// than the making nsis-tauri-utils depend on other plugins and re-export the DLLs +fn combine_plugins_and_write_to_out_dir() { let out_dir = std::env::var("OUT_DIR").unwrap(); let path = format!("{out_dir}/combined_libs.rs"); @@ -11,22 +16,27 @@ fn write_plugins() { .truncate(true) .write(true) .create(true) - .open(&path) + .open(path) .unwrap(); - let p1 = include_str!("../nsis-semvercompare/src/lib.rs"); - let p2 = include_str!("../nsis-process/src/lib.rs"); - for p in [p1, p2] { - let lines = p + for plugin in [ + include_str!("../nsis-semvercompare/src/lib.rs"), + include_str!("../nsis-process/src/lib.rs"), + ] { + let lines = plugin .lines() .filter(|l| { + // remove lines that should only be specified once + // either for compilation or for clippy !(l.contains("#![no_std]") - || l.contains("use nsis_plugin_api::*;") - || l.contains("nsis_plugin!();")) + || l.contains("nsis_plugin!();") + || l.contains("use nsis_plugin_api::*;")) }) + .take_while(|l| !l.contains("mod tests {")) .collect::>(); - let content = lines.join("\n"); + // skip last line which should be #[cfg(test)] + let content = lines[..lines.len() - 1].join("\n"); std::io::Write::write_all(&mut file, content.as_bytes()).unwrap(); } }