Skip to main content

wslplugins_rs/api/
utils.rs

1//! # WSL Version Checking Utilities
2//!
3//! This module provides utilities to verify that the current WSL version meets the required version for plugin compatibility.
4//! It includes functions to perform version checks and unit tests to ensure correctness.
5
6use super::errors::require_update_error::{Error, Result};
7use crate::cstring_ext::CstringExt;
8use crate::WSLContext;
9use crate::WSLVersion;
10use std::ffi::CString;
11use std::ptr;
12use typed_path::Utf8UnixPath;
13
14pub(crate) fn check_required_version_result(
15    current_version: &WSLVersion,
16    required_version: &WSLVersion,
17) -> Result<()> {
18    if current_version >= required_version {
19        Ok(())
20    } else {
21        Err(Error {
22            current_version: current_version.clone(),
23            required_version: required_version.clone(),
24        })
25    }
26}
27
28pub(crate) fn check_required_version_result_from_context(
29    wsl_context: Option<&WSLContext>,
30    required_version: &WSLVersion,
31) -> Result<()> {
32    wsl_context.map_or(Ok(()), |context| {
33        let current_version = context.api.version();
34        check_required_version_result(current_version, required_version)
35    })
36}
37#[inline]
38pub(super) fn encode_c_path(path: &Utf8UnixPath) -> Vec<u8> {
39    let bytes = path.as_str().as_bytes();
40    let mut out = Vec::with_capacity(bytes.len() + 1);
41    out.extend_from_slice(bytes);
42    out.push(0);
43    out
44}
45
46#[allow(clippy::similar_names, reason = "naming is clear")]
47pub(super) fn encode_c_argv<I>(args: I) -> (Vec<CString>, Vec<*const u8>)
48where
49    I: IntoIterator,
50    I::Item: AsRef<str>,
51{
52    let iter = args.into_iter();
53    let (lower, upper) = iter.size_hint();
54    let count = upper.unwrap_or(lower);
55
56    let mut c_args = Vec::<CString>::with_capacity(count);
57    let mut argv = Vec::<*const u8>::with_capacity(count + 1);
58
59    for arg in iter {
60        let c = CString::from_str_truncate(arg.as_ref());
61        // Pointer is stable: moving CString does not move its internal buffer.
62        argv.push(c.as_ptr().cast::<u8>());
63        c_args.push(c);
64    }
65
66    // NULL-terminated list as required by the API contract.
67    argv.push(ptr::null());
68
69    (c_args, argv)
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use crate::WSLVersion;
76
77    /// Tests that `check_required_version_result` returns `Ok` when the current version meets the requirement.
78    #[test]
79    fn test_check_required_version_result_ok() {
80        let current_version = WSLVersion::new(2, 1, 3);
81        let required_version = WSLVersion::new(2, 1, 2);
82
83        let result = check_required_version_result(&current_version, &required_version);
84
85        assert!(result.is_ok());
86    }
87
88    /// Tests that `check_required_version_result` returns `Err` when the current version is insufficient.
89    #[test]
90    fn test_check_required_version_result_error() {
91        let current_version = WSLVersion::new(2, 1, 1);
92        let required_version = WSLVersion::new(2, 1, 2);
93
94        let result = check_required_version_result(&current_version, &required_version);
95
96        assert!(result.is_err());
97    }
98}