Skip to main content

wslplugins_rs/plugin/
utils.rs

1//! # Plugin Creation and Result Handling Utilities
2//!
3//! This module provides utility functions for creating WSL plugins and handling results,
4//! enabling smooth integration with the WSL Plugin API.
5
6use windows_core::{Error as WinError, Result as WinResult, HRESULT};
7use wslpluginapi_sys::{windows_sys::Win32::Foundation::ERROR_ALREADY_INITIALIZED, WSLPluginAPIV1};
8
9use crate::WSLContext;
10
11#[cfg(doc)]
12use super::Error;
13use super::{Result, WSLPluginV1};
14
15/// Creates a WSL plugin instance with a specified required API version.
16///
17/// This function ensures that the provided WSL Plugin API meets the required version before
18/// creating a new plugin instance. If the API version does not meet the requirements, an error is returned.
19///
20/// # Type Parameters
21/// - `T`: A type implementing the [`WSLPluginV1`] trait, representing the plugin to create.
22///
23/// # Arguments
24/// - `api`: A reference to the WSL Plugin API version 1 structure.
25/// - `required_major`: The required major version of the API.
26/// - `required_minor`: The required minor version of the API.
27/// - `required_revision`: The required revision of the API.
28///
29/// # Returns
30/// - `Ok(plugin)`: The created plugin instance.
31/// - `Err(WinError)`: If the API version is insufficient or the plugin is already initialized.
32///
33/// # Errors
34/// - Returns <code>[WinError]::from([ERROR_ALREADY_INITIALIZED])</code> if a plugin is already initialized.
35/// - Returns <code>[WinError]::from([WSL_E_PLUGIN_REQUIRES_UPDATE](wslpluginapi_sys::WSL_E_PLUGIN_REQUIRES_UPDATE))</code> error if the API version is insufficient.
36#[inline]
37pub fn create_plugin_with_required_version<T: WSLPluginV1>(
38    api: &'static WSLPluginAPIV1,
39    required_major: u32,
40    required_minor: u32,
41    required_revision: u32,
42) -> WinResult<T> {
43    // SAFETY: As api reference exist it's safe to call it
44    unsafe {
45        HRESULT(wslpluginapi_sys::require_version(
46            required_major,
47            required_minor,
48            required_revision,
49            api,
50        ))
51        .ok()?;
52    };
53    WSLContext::init(api.as_ref())
54        .ok_or_else(|| WinError::from_hresult(HRESULT::from_win32(ERROR_ALREADY_INITIALIZED)))
55        .and_then(T::try_new)
56}
57
58#[expect(clippy::missing_errors_doc)]
59/// Converts a generic `Result<T>` using the custom `Error` type into a `WinResult<T>`.
60///
61/// This function simplifies the interoperability between the custom error handling
62/// in the WSL plugin system and the Windows error system by mapping the plugin [Error]
63/// into a [`windows_core::Error`] using the `consume_error_message_unwrap` method.
64///
65/// # Arguments
66/// - `result`: A [`Result<T>`] using the custom [Error] type defined in this crate.
67///
68/// # Returns
69/// A `WinResult<T>` where:
70/// - `Ok(value)` contains the successful result `T`.
71/// - `Err(error)` contains a [`windows_core::Error`] converted from the plugin [Error].
72///
73/// # Behavior
74/// - If the `result` is `Ok`, it is returned as-is.
75/// - If the `result` is `Err`, the error is consumed
76///   and sent to WSL and is then
77///   converted into a [`windows_core::Error`].
78///
79/// # Usage
80/// This utility is intended to facilitate the transition between idiomatic Rust
81/// error handling and the Windows API error-handling conventions.
82#[inline]
83pub fn consume_to_win_result<T>(result: Result<T>) -> WinResult<T> {
84    result.map_err(super::error::Error::consume_error_message_unwrap)
85}