Skip to content

Commit f043852

Browse files
authored
ref to ref (#7)
Change implementation to avoid lifetime and convert sys pointer to higher level pointer using memory transparency
1 parent 545d268 commit f043852

File tree

9 files changed

+222
-93
lines changed

9 files changed

+222
-93
lines changed

wslplugins-macro-core/src/generator/c_funcs_tokens.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ pub(super) fn get_c_func_tokens(hook: Hooks) -> Result<Option<TokenStream>> {
1818
let settings_ptr = unsafe { &*settings };
1919
if let Some(plugin) = PLUGIN.get() {
2020
let result = plugin.#trait_method_ident(
21-
&::wslplugins_rs::WSLSessionInformation::from(session_ptr),
22-
&::wslplugins_rs::WSLVmCreationSettings::from(settings_ptr),
21+
session_ptr.as_ref(),
22+
settings_ptr.as_ref(),
2323
);
2424
::wslplugins_rs::plugin::utils::consume_to_win_result(result).into()
2525
} else {
@@ -33,7 +33,7 @@ pub(super) fn get_c_func_tokens(hook: Hooks) -> Result<Option<TokenStream>> {
3333
) -> ::windows::core::HRESULT {
3434
let session_ptr = unsafe { &*session };
3535
if let Some(plugin) = PLUGIN.get() {
36-
plugin.#trait_method_ident(&::wslplugins_rs::WSLSessionInformation::from(session_ptr)).into()
36+
plugin.#trait_method_ident(session_ptr.as_ref()).into()
3737
} else {
3838
::windows::Win32::Foundation::E_FAIL
3939
}
@@ -48,8 +48,8 @@ pub(super) fn get_c_func_tokens(hook: Hooks) -> Result<Option<TokenStream>> {
4848
let distribution_ptr = unsafe { &*distribution };
4949
if let Some(plugin) = PLUGIN.get() {
5050
let result = plugin.#trait_method_ident(
51-
&::wslplugins_rs::WSLSessionInformation::from(session_ptr),
52-
&::wslplugins_rs::DistributionInformation::from(distribution_ptr),
51+
session_ptr.as_ref(),
52+
distribution_ptr.as_ref(),
5353
);
5454
::wslplugins_rs::plugin::utils::consume_to_win_result(result).into()
5555
} else {
@@ -66,8 +66,8 @@ pub(super) fn get_c_func_tokens(hook: Hooks) -> Result<Option<TokenStream>> {
6666
let distribution_ptr = unsafe { &*distribution };
6767
if let Some(plugin) = PLUGIN.get() {
6868
plugin.#trait_method_ident(
69-
&::wslplugins_rs::WSLSessionInformation::from(session_ptr),
70-
&::wslplugins_rs::DistributionInformation::from(distribution_ptr),
69+
session_ptr.as_ref(),
70+
distribution_ptr.as_ref(),
7171
).into()
7272
} else {
7373
::windows::Win32::Foundation::E_FAIL
@@ -83,8 +83,8 @@ pub(super) fn get_c_func_tokens(hook: Hooks) -> Result<Option<TokenStream>> {
8383
let distribution_ptr = unsafe { &*distribution };
8484
if let Some(plugin) = PLUGIN.get() {
8585
plugin.#trait_method_ident(
86-
&::wslplugins_rs::WSLSessionInformation::from(session_ptr),
87-
&::wslplugins_rs::OfflineDistributionInformation::from(distribution_ptr),
86+
session_ptr.as_ref(),
87+
distribution_ptr.as_ref(),
8888
).into()
8989
} else {
9090
::windows::Win32::Foundation::E_FAIL
@@ -100,8 +100,8 @@ pub(super) fn get_c_func_tokens(hook: Hooks) -> Result<Option<TokenStream>> {
100100
let distribution_ptr = unsafe { &*distribution };
101101
if let Some(plugin) = PLUGIN.get() {
102102
plugin.#trait_method_ident(
103-
&::wslplugins_rs::WSLSessionInformation::from(session_ptr),
104-
&::wslplugins_rs::OfflineDistributionInformation::from(distribution_ptr),
103+
session_ptr.as_ref(),
104+
distribution_ptr.as_ref(),
105105
).into()
106106
} else {
107107
::windows::Win32::Foundation::E_FAIL

wslplugins-rs/src/api/api_v1.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,34 @@ use super::utils::check_required_version_result;
3030
/// Represents a structured interface for interacting with the WSLPluginAPIV1 API.
3131
/// This struct encapsulates the methods provided by the WSLPluginAPIV1 API, allowing
3232
/// idiomatic interaction with the Windows Subsystem for Linux (WSL).
33-
pub struct ApiV1<'a>(&'a WSLPluginAPIV1);
33+
#[repr(transparent)]
34+
pub struct ApiV1(WSLPluginAPIV1);
3435

35-
/// Converts a raw reference to `WSLPluginAPIV1` into [ApiV1].
36-
impl<'a> From<&'a WSLPluginAPIV1> for ApiV1<'a> {
37-
fn from(value: &'a WSLPluginAPIV1) -> Self {
38-
Self(value)
36+
impl From<ApiV1> for WSLPluginAPIV1 {
37+
fn from(value: ApiV1) -> Self {
38+
value.0
3939
}
4040
}
4141

42-
impl ApiV1<'_> {
42+
impl From<WSLPluginAPIV1> for ApiV1 {
43+
fn from(value: WSLPluginAPIV1) -> Self {
44+
ApiV1(value)
45+
}
46+
}
47+
48+
impl AsRef<WSLPluginAPIV1> for ApiV1 {
49+
fn as_ref(&self) -> &WSLPluginAPIV1 {
50+
&self.0
51+
}
52+
}
53+
54+
impl AsRef<ApiV1> for WSLPluginAPIV1 {
55+
fn as_ref(&self) -> &ApiV1 {
56+
unsafe { &*(self as *const WSLPluginAPIV1 as *const ApiV1) }
57+
}
58+
}
59+
60+
impl ApiV1 {
4361
/// Returns the current version of the WSL API being used.
4462
///
4563
/// This is useful for checking compatibility with specific API features.
@@ -252,10 +270,21 @@ impl ApiV1<'_> {
252270
}
253271
}
254272

255-
impl Debug for ApiV1<'_> {
273+
impl Debug for ApiV1 {
256274
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257275
f.debug_struct("ApiV1")
258276
.field("version", self.version())
259277
.finish()
260278
}
261279
}
280+
281+
#[cfg(test)]
282+
mod tests {
283+
use super::*;
284+
use crate::utils::test_transparence;
285+
286+
#[test]
287+
fn test_layouts() {
288+
test_transparence::<WSLPluginAPIV1, ApiV1>();
289+
}
290+
}

wslplugins-rs/src/distribution_information.rs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,37 @@ use wslplugins_sys::WSLVersion;
3131
///
3232
/// This struct wraps the `WSLDistributionInformation` from the WSL Plugin API and provides
3333
/// safe, idiomatic Rust access to its fields.
34-
pub struct DistributionInformation<'a>(&'a wslplugins_sys::WSLDistributionInformation);
34+
#[repr(transparent)]
35+
pub struct DistributionInformation(wslplugins_sys::WSLDistributionInformation);
3536

36-
impl<'a> From<&'a wslplugins_sys::WSLDistributionInformation> for DistributionInformation<'a> {
37-
/// Creates a `DistributionInformation` instance from a reference to the raw WSL Plugin API structure.
38-
///
39-
/// # Arguments
40-
/// - `ptr`: A reference to a `WSLDistributionInformation` instance.
41-
///
42-
/// # Returns
43-
/// A wrapped `DistributionInformation` instance.
44-
fn from(ptr: &'a wslplugins_sys::WSLDistributionInformation) -> Self {
45-
Self(ptr)
37+
impl AsRef<DistributionInformation> for wslplugins_sys::WSLDistributionInformation {
38+
fn as_ref(&self) -> &DistributionInformation {
39+
unsafe {
40+
&*(self as *const wslplugins_sys::WSLDistributionInformation
41+
as *const DistributionInformation)
42+
}
43+
}
44+
}
45+
46+
impl From<DistributionInformation> for wslplugins_sys::WSLDistributionInformation {
47+
fn from(value: DistributionInformation) -> Self {
48+
value.0
49+
}
50+
}
51+
52+
impl AsRef<wslplugins_sys::WSLDistributionInformation> for DistributionInformation {
53+
fn as_ref(&self) -> &wslplugins_sys::WSLDistributionInformation {
54+
&self.0
55+
}
56+
}
57+
58+
impl From<wslplugins_sys::WSLDistributionInformation> for DistributionInformation {
59+
fn from(value: wslplugins_sys::WSLDistributionInformation) -> Self {
60+
DistributionInformation(value)
4661
}
4762
}
4863

49-
impl DistributionInformation<'_> {
64+
impl DistributionInformation {
5065
/// Retrieves the PID of the init process.
5166
///
5267
/// This requires API version 2.0.5 or higher. If the current API version does not meet
@@ -74,7 +89,7 @@ impl DistributionInformation<'_> {
7489
}
7590
}
7691

77-
impl CoreDistributionInformation for DistributionInformation<'_> {
92+
impl CoreDistributionInformation for DistributionInformation {
7893
/// Retrieves the unique ID of the distribution.
7994
///
8095
/// # Returns
@@ -108,7 +123,7 @@ impl CoreDistributionInformation for DistributionInformation<'_> {
108123
}
109124
}
110125

111-
impl<T> PartialEq<T> for DistributionInformation<'_>
126+
impl<T> PartialEq<T> for DistributionInformation
112127
where
113128
T: CoreDistributionInformation,
114129
{
@@ -118,14 +133,14 @@ where
118133
}
119134
}
120135

121-
impl Hash for DistributionInformation<'_> {
136+
impl Hash for DistributionInformation {
122137
/// Computes a hash based on the distribution's ID.
123138
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
124139
self.id().hash(state);
125140
}
126141
}
127142

128-
impl Display for DistributionInformation<'_> {
143+
impl Display for DistributionInformation {
129144
/// Formats the distribution information for display.
130145
///
131146
/// The output includes the distribution's name and ID.
@@ -134,7 +149,7 @@ impl Display for DistributionInformation<'_> {
134149
}
135150
}
136151

137-
impl Debug for DistributionInformation<'_> {
152+
impl Debug for DistributionInformation {
138153
/// Formats the distribution information for debugging.
139154
///
140155
/// The output includes:
@@ -156,3 +171,14 @@ impl Debug for DistributionInformation<'_> {
156171
}
157172
}
158173
}
174+
175+
#[cfg(test)]
176+
mod tests {
177+
use super::*;
178+
use crate::utils::test_transparence;
179+
180+
#[test]
181+
fn test_layouts() {
182+
test_transparence::<wslplugins_sys::WSLDistributionInformation, DistributionInformation>();
183+
}
184+
}

wslplugins-rs/src/offline_distribution_information.rs

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,37 @@ use windows::core::GUID;
1717
///
1818
/// This struct allows access to the details of an offline WSL distribution, including
1919
/// its ID, name, and optional package family name.
20-
///
21-
/// # Lifetime Parameters
22-
/// - `'a`: The lifetime of the referenced `WslOfflineDistributionInformation` instance.
23-
pub struct OfflineDistributionInformation<'a>(
24-
&'a wslplugins_sys::WslOfflineDistributionInformation,
25-
);
20+
#[repr(transparent)]
21+
pub struct OfflineDistributionInformation(wslplugins_sys::WslOfflineDistributionInformation);
2622

27-
impl<'a> OfflineDistributionInformation<'a> {
28-
/// Creates a new `OfflineDistributionInformation` instance from a raw pointer.
29-
///
30-
/// # Arguments
31-
/// - `ptr`: A reference to a `WslOfflineDistributionInformation` instance.
32-
///
33-
/// # Returns
34-
/// A safe wrapper around the provided pointer.
35-
pub fn from(ptr: &'a wslplugins_sys::WslOfflineDistributionInformation) -> Self {
36-
Self(ptr)
23+
impl From<OfflineDistributionInformation> for wslplugins_sys::WslOfflineDistributionInformation {
24+
fn from(value: OfflineDistributionInformation) -> Self {
25+
value.0
26+
}
27+
}
28+
29+
impl From<wslplugins_sys::WslOfflineDistributionInformation> for OfflineDistributionInformation {
30+
fn from(value: wslplugins_sys::WslOfflineDistributionInformation) -> Self {
31+
OfflineDistributionInformation(value)
32+
}
33+
}
34+
35+
impl AsRef<wslplugins_sys::WslOfflineDistributionInformation> for OfflineDistributionInformation {
36+
fn as_ref(&self) -> &wslplugins_sys::WslOfflineDistributionInformation {
37+
&self.0
3738
}
3839
}
3940

40-
impl CoreDistributionInformation for OfflineDistributionInformation<'_> {
41+
impl AsRef<OfflineDistributionInformation> for wslplugins_sys::WslOfflineDistributionInformation {
42+
fn as_ref(&self) -> &OfflineDistributionInformation {
43+
unsafe {
44+
&*(self as *const wslplugins_sys::WslOfflineDistributionInformation
45+
as *const OfflineDistributionInformation)
46+
}
47+
}
48+
}
49+
50+
impl CoreDistributionInformation for OfflineDistributionInformation {
4151
/// Retrieves the [GUID] of the offline distribution.
4252
fn id(&self) -> GUID {
4353
self.0.Id
@@ -65,7 +75,7 @@ impl CoreDistributionInformation for OfflineDistributionInformation<'_> {
6575
}
6676
}
6777

68-
impl<T> PartialEq<T> for OfflineDistributionInformation<'_>
78+
impl<T> PartialEq<T> for OfflineDistributionInformation
6979
where
7080
T: CoreDistributionInformation,
7181
{
@@ -75,14 +85,14 @@ where
7585
}
7686
}
7787

78-
impl Hash for OfflineDistributionInformation<'_> {
88+
impl Hash for OfflineDistributionInformation {
7989
/// Computes a hash based on the distribution's ID.
8090
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
8191
self.id().hash(state);
8292
}
8393
}
8494

85-
impl Display for OfflineDistributionInformation<'_> {
95+
impl Display for OfflineDistributionInformation {
8696
/// Formats the offline distribution information for display.
8797
///
8898
/// The output includes the distribution's name and ID.
@@ -91,7 +101,7 @@ impl Display for OfflineDistributionInformation<'_> {
91101
}
92102
}
93103

94-
impl Debug for OfflineDistributionInformation<'_> {
104+
impl Debug for OfflineDistributionInformation {
95105
/// Formats the offline distribution information for debugging.
96106
///
97107
/// The output includes the distribution's name, ID, and package family name.
@@ -103,3 +113,17 @@ impl Debug for OfflineDistributionInformation<'_> {
103113
.finish()
104114
}
105115
}
116+
117+
#[cfg(test)]
118+
mod tests {
119+
use super::*;
120+
use crate::utils::test_transparence;
121+
122+
#[test]
123+
fn test_layouts() {
124+
test_transparence::<
125+
wslplugins_sys::WslOfflineDistributionInformation,
126+
OfflineDistributionInformation,
127+
>();
128+
}
129+
}

wslplugins-rs/src/plugin/utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use windows::{
99
};
1010
use wslplugins_sys::WSLPluginAPIV1;
1111

12-
use crate::{api::ApiV1, WSLContext};
12+
use crate::WSLContext;
1313

1414
#[cfg(doc)]
1515
use super::Error;
@@ -50,7 +50,7 @@ pub fn create_plugin_with_required_version<T: WSLPluginV1>(
5050
wslplugins_sys::require_version(required_major, required_minor, required_revision, api)
5151
.ok()?;
5252
}
53-
if let Some(context) = WSLContext::init(ApiV1::from(api)) {
53+
if let Some(context) = WSLContext::init(api.as_ref()) {
5454
let plugin = T::try_new(context)?;
5555
Ok(plugin)
5656
} else {

wslplugins-rs/src/utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ pub fn cstring_from_str(input: &str) -> CString {
2020
unsafe { CString::from_vec_unchecked(filtered_input) }
2121
}
2222

23+
#[cfg(test)]
24+
pub(crate) fn test_transparence<T, U>() {
25+
assert_eq!(align_of::<T>(), align_of::<U>());
26+
assert_eq!(size_of::<T>(), size_of::<U>());
27+
}
28+
2329
#[cfg(test)]
2430
mod tests {
2531
use super::*;

wslplugins-rs/src/wsl_context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static CURRENT_CONTEXT: OnceLock<WSLContext> = OnceLock::new();
1616
/// throughout the plugin's lifecycle.
1717
pub struct WSLContext {
1818
/// The API interface used for interacting with the WSL plugin API.
19-
pub api: ApiV1<'static>,
19+
pub api: &'static ApiV1,
2020
}
2121

2222
impl WSLContext {
@@ -59,7 +59,7 @@ impl WSLContext {
5959
/// # Returns
6060
/// - `Some(&'static WSLContext)`: If the context was successfully initialized.
6161
/// - `None`: If the context has already been initialized.
62-
pub fn init(api: ApiV1<'static>) -> Option<&'static Self> {
62+
pub fn init(api: &'static ApiV1) -> Option<&'static Self> {
6363
CURRENT_CONTEXT.set(WSLContext { api }).ok()?;
6464
CURRENT_CONTEXT.get()
6565
}

0 commit comments

Comments
 (0)