wslplugins_rs/
offline_distribution_information.rs1use crate::{
7 api::{
8 errors::require_update_error::Result, utils::check_required_version_result_from_context,
9 },
10 core_distribution_information::CoreDistributionInformation,
11 UserDistributionID, WSLContext, WSLVersion,
12};
13use std::{
14 ffi::OsString,
15 fmt::{self, Debug, Display},
16 hash::{Hash, Hasher},
17 os::windows::ffi::OsStringExt as _,
18 ptr,
19};
20use windows_core::PCWSTR;
21
22#[repr(transparent)]
27pub struct OfflineDistributionInformation(wslpluginapi_sys::WslOfflineDistributionInformation);
28
29impl From<OfflineDistributionInformation> for wslpluginapi_sys::WslOfflineDistributionInformation {
30 #[inline]
31 fn from(value: OfflineDistributionInformation) -> Self {
32 value.0
33 }
34}
35
36impl From<wslpluginapi_sys::WslOfflineDistributionInformation> for OfflineDistributionInformation {
37 #[inline]
38 fn from(value: wslpluginapi_sys::WslOfflineDistributionInformation) -> Self {
39 Self(value)
40 }
41}
42
43impl AsRef<wslpluginapi_sys::WslOfflineDistributionInformation> for OfflineDistributionInformation {
44 #[inline]
45 fn as_ref(&self) -> &wslpluginapi_sys::WslOfflineDistributionInformation {
46 &self.0
47 }
48}
49
50impl AsRef<OfflineDistributionInformation> for wslpluginapi_sys::WslOfflineDistributionInformation {
51 #[inline]
52 fn as_ref(&self) -> &OfflineDistributionInformation {
53 unsafe { &*ptr::from_ref::<Self>(self).cast::<OfflineDistributionInformation>() }
55 }
56}
57
58impl CoreDistributionInformation for OfflineDistributionInformation {
59 #[inline]
60 fn id(&self) -> UserDistributionID {
61 self.0.Id.into()
62 }
63
64 #[inline]
66 fn name(&self) -> OsString {
67 unsafe { OsString::from_wide(PCWSTR::from_raw(self.0.Name).as_wide()) }
69 }
70
71 #[inline]
77 fn package_family_name(&self) -> Option<OsString> {
78 unsafe {
80 let ptr = PCWSTR::from_raw(self.0.PackageFamilyName);
81 if ptr.is_null() || ptr.is_empty() {
82 None
83 } else {
84 Some(OsString::from_wide(ptr.as_wide()))
85 }
86 }
87 }
88
89 #[inline]
90 fn flavor(&self) -> Result<Option<OsString>> {
91 check_required_version_result_from_context(
92 WSLContext::get_current(),
93 &WSLVersion::new(2, 4, 4),
94 )?;
95
96 unsafe {
98 let ptr = PCWSTR::from_raw(self.0.Flavor);
99 if ptr.is_null() || ptr.is_empty() {
100 Ok(None)
101 } else {
102 Ok(Some(OsString::from_wide(ptr.as_wide())))
103 }
104 }
105 }
106
107 #[inline]
108 fn version(&self) -> Result<Option<OsString>> {
109 check_required_version_result_from_context(
110 WSLContext::get_current(),
111 &WSLVersion::new(2, 4, 4),
112 )?;
113 unsafe {
115 let ptr = PCWSTR::from_raw(self.0.Version);
116 if ptr.is_null() || ptr.is_empty() {
117 Ok(None)
118 } else {
119 Ok(Some(OsString::from_wide(ptr.as_wide())))
120 }
121 }
122 }
123}
124
125impl<T> PartialEq<T> for OfflineDistributionInformation
126where
127 T: CoreDistributionInformation,
128{
129 #[inline]
131 fn eq(&self, other: &T) -> bool {
132 self.id() == other.id()
133 }
134}
135
136impl Hash for OfflineDistributionInformation {
137 #[inline]
139 fn hash<H: Hasher>(&self, state: &mut H) {
140 self.id().hash(state);
141 }
142}
143
144impl Display for OfflineDistributionInformation {
145 #[inline]
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 unsafe {
149 write!(
150 f,
151 "{} {{{}}}",
152 PCWSTR::from_raw(self.0.Name).display(),
153 self.id()
154 )
155 }
156 }
157}
158
159impl Debug for OfflineDistributionInformation {
160 #[inline]
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 let mut dbg = f.debug_struct("DistributionInformation");
163 dbg.field("name", &self.name())
164 .field("id", &self.id())
165 .field("package_family_name", &self.package_family_name());
166 let mut exhaustive = true;
167 if let Ok(flavor) = self.flavor() {
168 dbg.field("flavor", &flavor);
169 } else {
170 exhaustive = false;
171 }
172 if let Ok(version) = self.version() {
173 dbg.field("version", &version);
174 } else {
175 exhaustive = false;
176 }
177 if exhaustive {
178 dbg.finish()
179 } else {
180 dbg.finish_non_exhaustive()
181 }
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use crate::utils::test_transparence;
189
190 #[test]
191 fn test_layouts() {
192 test_transparence::<
193 wslpluginapi_sys::WslOfflineDistributionInformation,
194 OfflineDistributionInformation,
195 >();
196 }
197}