use {super::ModuleId, crate::api::version::Version};
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct ModuleProbe {
pub id: [u8; 64],
pub name: [u8; 128],
pub version: Version,
pub api_version: Version,
pub rustc_version: [u8; 64],
pub required_deps_count: u8,
pub required_deps: [[u8; 64]; 8],
pub optional_deps_count: u8,
pub optional_deps: [[u8; 64]; 8],
}
impl ModuleProbe {
#[must_use]
pub const fn new(id: &str, name: &str, version: Version, api_version: Version) -> Self {
let mut probe = Self {
id: [0; 64],
name: [0; 128],
version,
api_version,
rustc_version: [0; 64],
required_deps_count: 0,
required_deps: [[0; 64]; 8],
optional_deps_count: 0,
optional_deps: [[0; 64]; 8],
};
let id_bytes = id.as_bytes();
let id_len = if id_bytes.len() < 63 {
id_bytes.len()
} else {
63
};
let mut i = 0;
while i < id_len {
probe.id[i] = id_bytes[i];
i += 1;
}
let name_bytes = name.as_bytes();
let name_len = if name_bytes.len() < 127 {
name_bytes.len()
} else {
127
};
i = 0;
while i < name_len {
probe.name[i] = name_bytes[i];
i += 1;
}
probe
}
#[must_use]
pub fn id_str(&self) -> &str {
let len = self
.id
.iter()
.position(|&b| b == 0)
.unwrap_or(self.id.len());
std::str::from_utf8(&self.id[..len]).unwrap_or("")
}
#[must_use]
pub fn name_str(&self) -> &str {
let len = self
.name
.iter()
.position(|&b| b == 0)
.unwrap_or(self.name.len());
std::str::from_utf8(&self.name[..len]).unwrap_or("")
}
#[must_use]
pub fn rustc_version_str(&self) -> &str {
let len = self
.rustc_version
.iter()
.position(|&b| b == 0)
.unwrap_or(self.rustc_version.len());
std::str::from_utf8(&self.rustc_version[..len]).unwrap_or("")
}
#[must_use]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn required_deps(&self) -> Vec<ModuleId> {
let count = (self.required_deps_count as usize).min(8);
(0..count)
.filter_map(|i| {
let len = self.required_deps[i]
.iter()
.position(|&b| b == 0)
.unwrap_or(64);
if len == 0 {
None
} else {
std::str::from_utf8(&self.required_deps[i][..len])
.ok()
.map(|s| ModuleId::from_string(s.to_string()))
}
})
.collect()
}
#[must_use]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn optional_deps(&self) -> Vec<ModuleId> {
let count = (self.optional_deps_count as usize).min(8);
(0..count)
.filter_map(|i| {
let len = self.optional_deps[i]
.iter()
.position(|&b| b == 0)
.unwrap_or(64);
if len == 0 {
None
} else {
std::str::from_utf8(&self.optional_deps[i][..len])
.ok()
.map(|s| ModuleId::from_string(s.to_string()))
}
})
.collect()
}
#[must_use]
pub const fn with_rustc_version(mut self, version: &str) -> Self {
let bytes = version.as_bytes();
let len = if bytes.len() < 63 { bytes.len() } else { 63 };
let mut i = 0;
while i < len {
self.rustc_version[i] = bytes[i];
i += 1;
}
self
}
#[must_use]
#[allow(clippy::cast_possible_truncation)] #[cfg_attr(coverage_nightly, coverage(off))]
pub const fn with_required_dep(mut self, index: usize, dep: &str) -> Self {
if index >= 8 {
return self;
}
let bytes = dep.as_bytes();
let len = if bytes.len() < 63 { bytes.len() } else { 63 };
let mut i = 0;
while i < len {
self.required_deps[index][i] = bytes[i];
i += 1;
}
if index as u8 >= self.required_deps_count {
self.required_deps_count = (index + 1) as u8;
}
self
}
#[must_use]
#[allow(clippy::cast_possible_truncation)] #[cfg_attr(coverage_nightly, coverage(off))]
pub const fn with_optional_dep(mut self, index: usize, dep: &str) -> Self {
if index >= 8 {
return self;
}
let bytes = dep.as_bytes();
let len = if bytes.len() < 63 { bytes.len() } else { 63 };
let mut i = 0;
while i < len {
self.optional_deps[index][i] = bytes[i];
i += 1;
}
if index as u8 >= self.optional_deps_count {
self.optional_deps_count = (index + 1) as u8;
}
self
}
}