wslplugins_rs/
distribution_information.rs1#[cfg(doc)]
16use crate::api::errors::require_update_error::Error;
17use crate::api::{
18 errors::require_update_error::Result, utils::check_required_version_result_from_context,
19};
20use crate::core_distribution_information::CoreDistributionInformation;
21use crate::WSLVersion;
22use crate::{UserDistributionID, WSLContext};
23use std::ffi::OsString;
24use std::fmt::{self, Debug, Display};
25use std::hash::{Hash, Hasher};
26use std::os::windows::ffi::OsStringExt as _;
27use std::ptr;
28use windows_core::PCWSTR;
29
30#[repr(transparent)]
35pub struct DistributionInformation(wslpluginapi_sys::WSLDistributionInformation);
36
37impl AsRef<DistributionInformation> for wslpluginapi_sys::WSLDistributionInformation {
38 #[inline]
39 fn as_ref(&self) -> &DistributionInformation {
40 unsafe { &*ptr::from_ref::<Self>(self).cast::<DistributionInformation>() }
42 }
43}
44
45impl From<DistributionInformation> for wslpluginapi_sys::WSLDistributionInformation {
46 #[inline]
47 fn from(value: DistributionInformation) -> Self {
48 value.0
49 }
50}
51
52impl AsRef<wslpluginapi_sys::WSLDistributionInformation> for DistributionInformation {
53 #[inline]
54 fn as_ref(&self) -> &wslpluginapi_sys::WSLDistributionInformation {
55 &self.0
56 }
57}
58
59impl From<wslpluginapi_sys::WSLDistributionInformation> for DistributionInformation {
60 #[inline]
61 fn from(value: wslpluginapi_sys::WSLDistributionInformation) -> Self {
62 Self(value)
63 }
64}
65
66impl DistributionInformation {
67 #[inline]
77 pub fn init_pid(&self) -> Result<u32> {
78 check_required_version_result_from_context(
79 WSLContext::get_current(),
80 &WSLVersion::new(2, 0, 5),
81 )?;
82 Ok(self.0.InitPid)
83 }
84
85 #[inline]
91 #[must_use]
92 pub const fn pid_namespace(&self) -> u64 {
93 self.0.PidNamespace
94 }
95}
96
97impl CoreDistributionInformation for DistributionInformation {
98 #[inline]
99 fn id(&self) -> UserDistributionID {
100 self.0.Id.into()
101 }
102
103 #[inline]
104 fn name(&self) -> OsString {
105 unsafe { OsString::from_wide(PCWSTR::from_raw(self.0.Name).as_wide()) }
107 }
108
109 #[inline]
110 fn package_family_name(&self) -> Option<OsString> {
111 unsafe {
113 let ptr = self.0.PackageFamilyName;
114 if ptr.is_null() {
115 None
116 } else {
117 Some(OsString::from_wide(PCWSTR::from_raw(ptr).as_wide()))
118 }
119 }
120 }
121
122 #[inline]
123 fn flavor(&self) -> Result<Option<OsString>> {
124 check_required_version_result_from_context(
125 WSLContext::get_current(),
126 &WSLVersion::new(2, 4, 4),
127 )?;
128 unsafe {
130 let ptr = self.0.Flavor;
131 if ptr.is_null() {
132 Ok(None)
133 } else {
134 Ok(Some(OsString::from_wide(PCWSTR::from_raw(ptr).as_wide())))
135 }
136 }
137 }
138
139 #[inline]
140 fn version(&self) -> Result<Option<OsString>> {
141 check_required_version_result_from_context(
142 WSLContext::get_current(),
143 &WSLVersion::new(2, 4, 4),
144 )?;
145 unsafe {
147 let ptr = self.0.Version;
148 if ptr.is_null() {
149 Ok(None)
150 } else {
151 Ok(Some(OsString::from_wide(PCWSTR::from_raw(ptr).as_wide())))
152 }
153 }
154 }
155}
156
157impl<T> PartialEq<T> for DistributionInformation
158where
159 T: CoreDistributionInformation,
160{
161 #[inline]
163 fn eq(&self, other: &T) -> bool {
164 self.id() == other.id()
165 }
166}
167
168impl Hash for DistributionInformation {
169 #[inline]
171 fn hash<H: Hasher>(&self, state: &mut H) {
172 self.id().hash(state);
173 }
174}
175
176impl Display for DistributionInformation {
177 #[inline]
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 unsafe {
181 write!(
182 f,
183 "{} {{{}}}",
184 PCWSTR::from_raw(self.0.Name).display(),
185 self.id()
186 )
187 }
188 }
189}
190
191impl Debug for DistributionInformation {
192 #[inline]
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 let mut dbg = f.debug_struct("DistributionInformation");
195 dbg.field("name", &self.name())
196 .field("id", &self.id())
197 .field("package_family_name", &self.package_family_name())
198 .field("pid_namespace", &self.pid_namespace());
199 let mut exhaustive = true;
200
201 if let Ok(pid) = self.init_pid() {
202 dbg.field("init_pid", &pid);
203 } else {
204 exhaustive = false;
205 }
206 if let Ok(flavor) = self.flavor() {
207 dbg.field("flavor", &flavor);
208 } else {
209 exhaustive = false;
210 }
211 if let Ok(version) = self.version() {
212 dbg.field("version", &version);
213 } else {
214 exhaustive = false;
215 }
216
217 if exhaustive {
218 dbg.finish()
219 } else {
220 dbg.finish_non_exhaustive()
221 }
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228 use crate::utils::test_transparence;
229
230 #[test]
231 fn test_layouts() {
232 test_transparence::<wslpluginapi_sys::WSLDistributionInformation, DistributionInformation>(
233 );
234 }
235}