#[cfg(doc)]
use crate::api::errors::require_update_error::Error;
use crate::api::{
errors::require_update_error::Result, utils::check_required_version_result_from_context,
};
use crate::core_distribution_information::CoreDistributionInformation;
use crate::WSLVersion;
use crate::{UserDistributionID, WSLContext};
use std::ffi::OsString;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::os::windows::ffi::OsStringExt as _;
use std::ptr;
use windows_core::PCWSTR;
#[repr(transparent)]
pub struct DistributionInformation(wslpluginapi_sys::WSLDistributionInformation);
impl AsRef<DistributionInformation> for wslpluginapi_sys::WSLDistributionInformation {
#[inline]
fn as_ref(&self) -> &DistributionInformation {
unsafe { &*ptr::from_ref::<Self>(self).cast::<DistributionInformation>() }
}
}
impl From<DistributionInformation> for wslpluginapi_sys::WSLDistributionInformation {
#[inline]
fn from(value: DistributionInformation) -> Self {
value.0
}
}
impl AsRef<wslpluginapi_sys::WSLDistributionInformation> for DistributionInformation {
#[inline]
fn as_ref(&self) -> &wslpluginapi_sys::WSLDistributionInformation {
&self.0
}
}
impl From<wslpluginapi_sys::WSLDistributionInformation> for DistributionInformation {
#[inline]
fn from(value: wslpluginapi_sys::WSLDistributionInformation) -> Self {
Self(value)
}
}
impl DistributionInformation {
#[inline]
pub fn init_pid(&self) -> Result<u32> {
check_required_version_result_from_context(
WSLContext::get_current(),
&WSLVersion::new(2, 0, 5),
)?;
Ok(self.0.InitPid)
}
#[inline]
#[must_use]
pub const fn pid_namespace(&self) -> u64 {
self.0.PidNamespace
}
}
impl CoreDistributionInformation for DistributionInformation {
#[inline]
fn id(&self) -> UserDistributionID {
self.0.Id.into()
}
#[inline]
fn name(&self) -> OsString {
unsafe { OsString::from_wide(PCWSTR::from_raw(self.0.Name).as_wide()) }
}
#[inline]
fn package_family_name(&self) -> Option<OsString> {
unsafe {
let ptr = self.0.PackageFamilyName;
if ptr.is_null() {
None
} else {
Some(OsString::from_wide(PCWSTR::from_raw(ptr).as_wide()))
}
}
}
#[inline]
fn flavor(&self) -> Result<Option<OsString>> {
check_required_version_result_from_context(
WSLContext::get_current(),
&WSLVersion::new(2, 4, 4),
)?;
unsafe {
let ptr = self.0.Flavor;
if ptr.is_null() {
Ok(None)
} else {
Ok(Some(OsString::from_wide(PCWSTR::from_raw(ptr).as_wide())))
}
}
}
#[inline]
fn version(&self) -> Result<Option<OsString>> {
check_required_version_result_from_context(
WSLContext::get_current(),
&WSLVersion::new(2, 4, 4),
)?;
unsafe {
let ptr = self.0.Version;
if ptr.is_null() {
Ok(None)
} else {
Ok(Some(OsString::from_wide(PCWSTR::from_raw(ptr).as_wide())))
}
}
}
}
impl<T> PartialEq<T> for DistributionInformation
where
T: CoreDistributionInformation,
{
#[inline]
fn eq(&self, other: &T) -> bool {
self.id() == other.id()
}
}
impl Hash for DistributionInformation {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.id().hash(state);
}
}
impl Display for DistributionInformation {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
write!(
f,
"{} {{{}}}",
PCWSTR::from_raw(self.0.Name).display(),
self.id()
)
}
}
}
impl Debug for DistributionInformation {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut dbg = f.debug_struct("DistributionInformation");
dbg.field("name", &self.name())
.field("id", &self.id())
.field("package_family_name", &self.package_family_name())
.field("pid_namespace", &self.pid_namespace());
let mut exhaustive = true;
if let Ok(pid) = self.init_pid() {
dbg.field("init_pid", &pid);
} else {
exhaustive = false;
}
if let Ok(flavor) = self.flavor() {
dbg.field("flavor", &flavor);
} else {
exhaustive = false;
}
if let Ok(version) = self.version() {
dbg.field("version", &version);
} else {
exhaustive = false;
}
if exhaustive {
dbg.finish()
} else {
dbg.finish_non_exhaustive()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::test_transparence;
#[test]
fn test_layouts() {
test_transparence::<wslpluginapi_sys::WSLDistributionInformation, DistributionInformation>(
);
}
}