use super::header::Handle;
use super::undefined_struct::{UndefinedStruct, UndefinedStructTable};
use crate::structs::{DefinedStructTable, SMBiosStruct};
use serde::{ser::SerializeStruct, Serialize, Serializer};
use std::io::Error;
use std::{cmp::Ordering, slice::Iter};
use std::{fmt, fs::read};
pub struct SMBiosData {
table: UndefinedStructTable,
pub version: Option<SMBiosVersion>,
}
impl<'a> SMBiosData {
pub fn new(table: UndefinedStructTable, version: Option<SMBiosVersion>) -> Self {
Self { table, version }
}
pub fn from_vec_and_version(data: Vec<u8>, version: Option<SMBiosVersion>) -> Self {
Self {
table: UndefinedStructTable::from(data),
version,
}
}
pub fn try_load_from_file(
filename: &str,
version: Option<SMBiosVersion>,
) -> Result<SMBiosData, Error> {
let data = read(filename)?;
let result = Self {
table: UndefinedStructTable::from(data),
version,
};
Ok(result)
}
pub fn iter(&self) -> Iter<'_, UndefinedStruct> {
self.table.iter()
}
pub fn defined_struct_iter<T: 'a>(&'a self) -> impl Iterator<Item = T> + 'a
where
T: SMBiosStruct<'a>,
{
self.table.defined_struct_iter()
}
pub fn all<T, F>(&'a self, f: F) -> bool
where
T: SMBiosStruct<'a>,
F: FnMut(T) -> bool,
{
self.table.all(f)
}
pub fn any<T, F>(&'a self, f: F) -> bool
where
T: SMBiosStruct<'a>,
F: FnMut(T) -> bool,
{
self.table.any(f)
}
pub fn first<T>(&'a self) -> Option<T>
where
T: SMBiosStruct<'a>,
{
self.table.first()
}
pub fn find<T, P>(&'a self, predicate: P) -> Option<T>
where
T: SMBiosStruct<'a>,
P: FnMut(&T) -> bool,
{
self.table.find(predicate)
}
pub fn find_map<A, B, F>(&'a self, f: F) -> Option<B>
where
A: SMBiosStruct<'a>,
F: FnMut(A) -> Option<B>,
{
self.table.find_map(f)
}
pub fn filter<T: 'a, P: 'a>(&'a self, predicate: P) -> impl Iterator<Item = T> + 'a
where
T: SMBiosStruct<'a>,
P: FnMut(&T) -> bool,
{
self.table.filter(predicate)
}
pub fn map<A: 'a, B: 'a, F: 'a>(&'a self, f: F) -> impl Iterator<Item = B> + 'a
where
A: SMBiosStruct<'a>,
F: FnMut(A) -> B,
{
self.table.map(f)
}
pub fn filter_map<A: 'a, B: 'a, F: 'a>(&'a self, f: F) -> impl Iterator<Item = B> + 'a
where
A: SMBiosStruct<'a>,
F: FnMut(A) -> Option<B>,
{
self.table.filter_map(f)
}
pub fn find_by_handle(&'a self, handle: &Handle) -> Option<&UndefinedStruct> {
self.table.find_by_handle(handle)
}
pub fn collect<T>(&'a self) -> Vec<T>
where
T: SMBiosStruct<'a>,
{
self.table.collect()
}
}
impl IntoIterator for SMBiosData {
type Item = UndefinedStruct;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.table.into_iter()
}
}
impl fmt::Debug for SMBiosData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let defined_table: DefinedStructTable<'_> = self.table.iter().collect();
fmt.debug_struct(std::any::type_name::<SMBiosData>())
.field("version", &self.version)
.field("table", &defined_table)
.finish()
}
}
impl Serialize for SMBiosData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let defined_table: DefinedStructTable<'_> = self.table.iter().collect();
let mut state = serializer.serialize_struct("SMBiosData", 2)?;
state.serialize_field("version", &self.version)?;
state.serialize_field("table", &defined_table)?;
state.end()
}
}
#[derive(Debug, Eq, PartialEq, Serialize, Clone, Copy)]
pub struct SMBiosVersion {
pub major: u8,
pub minor: u8,
pub revision: u8,
}
impl SMBiosVersion {
pub fn new(major: u8, minor: u8, revision: u8) -> SMBiosVersion {
SMBiosVersion {
major,
minor,
revision,
}
}
}
impl Ord for SMBiosVersion {
fn cmp(&self, other: &Self) -> Ordering {
if self.major < other.major {
Ordering::Less
} else if self.major > other.major {
Ordering::Greater
} else if self.minor < other.minor {
Ordering::Less
} else if self.minor > other.minor {
Ordering::Greater
} else if self.revision < other.revision {
Ordering::Less
} else if self.revision > other.revision {
Ordering::Greater
} else {
Ordering::Equal
}
}
}
impl PartialOrd for SMBiosVersion {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}