use super::helpers::*;
pub trait DsdtObject {
fn append_to_vec(&self, byte_stream: &mut Vec<u8>);
fn to_bytes(&self) -> Vec<u8> {
let mut byte_stream = Vec::new();
self.append_to_vec(&mut byte_stream);
byte_stream
}
}
pub struct NamedObject {
name: Vec<u8>,
object: Vec<u8>,
}
impl NamedObject {
pub fn new(name: &[u8], object: &impl DsdtObject) -> Self {
let encoded_name = encode_name(name);
assert!(!encoded_name.is_empty());
NamedObject {
name: encoded_name,
object: object.to_bytes(),
}
}
}
impl DsdtObject for NamedObject {
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
byte_stream.push(8);
byte_stream.extend_from_slice(&self.name);
byte_stream.extend_from_slice(&self.object);
}
}
pub struct GenericObject<T: AsRef<[u8]>>(pub T);
impl<T> DsdtObject for GenericObject<T>
where
T: AsRef<[u8]>,
{
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
let buffer = self.0.as_ref();
byte_stream.extend_from_slice(buffer);
}
}
pub struct NamedInteger {
data: NamedObject,
}
impl NamedInteger {
pub fn new(name: &[u8], value: u64) -> Self {
Self {
data: NamedObject::new(name, &GenericObject(encode_integer(value))),
}
}
}
impl DsdtObject for NamedInteger {
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
self.data.append_to_vec(byte_stream);
}
}
pub struct NamedString {
data: NamedObject,
}
impl NamedString {
pub fn new(name: &[u8], value: &[u8]) -> Self {
Self {
data: NamedObject::new(name, &GenericObject(encode_string(value))),
}
}
}
impl DsdtObject for NamedString {
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
self.data.append_to_vec(byte_stream);
}
}
pub struct StructuredPackage<T: AsRef<[u8]>> {
pub elem_count: u8,
pub elem_data: T,
}
impl<T> DsdtObject for StructuredPackage<T>
where
T: AsRef<[u8]>,
{
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
let buffer = self.elem_data.as_ref();
byte_stream.push(0x12);
byte_stream.extend_from_slice(&encode_package_len(buffer.len() + 1));
byte_stream.push(self.elem_count);
byte_stream.extend_from_slice(buffer);
}
}
pub struct Package<T: AsRef<[u8]>>(pub T);
impl<T> DsdtObject for Package<T>
where
T: AsRef<[u8]>,
{
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
let buffer = self.0.as_ref();
StructuredPackage {
elem_count: buffer.len() as u8,
elem_data: buffer,
}
.append_to_vec(byte_stream);
}
}
pub struct Buffer<T: AsRef<[u8]>>(pub T);
impl<T> DsdtObject for Buffer<T>
where
T: AsRef<[u8]>,
{
fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
let buffer = self.0.as_ref();
let encoded_len = encode_integer(buffer.len().try_into().unwrap());
byte_stream.push(0x11);
byte_stream.extend_from_slice(&encode_package_len(buffer.len() + encoded_len.len()));
byte_stream.extend_from_slice(&encoded_len);
byte_stream.extend_from_slice(buffer);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dsdt::tests::verify_expected_bytes;
#[test]
fn verify_package() {
let package = Package(vec![1, 2, 3, 4]);
let bytes = package.to_bytes();
verify_expected_bytes(&bytes, &[0x12, 6, 4, 1, 2, 3, 4]);
}
#[test]
fn verify_large_package() {
let package = Package(vec![0; 0xff]);
let bytes = package.to_bytes();
assert_eq!(bytes.len(), 0xff + 4);
verify_expected_bytes(&bytes[..5], &[0x12, (1 << 6) | 2, 0x10, 0xff, 0]);
assert_eq!(bytes[0xff + 3], 0);
}
#[test]
fn verify_named_object() {
let package = Package(vec![0]);
let nobj = NamedObject::new(b"FOO", &package);
let bytes = nobj.to_bytes();
verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0x12, 3, 1, 0]);
}
#[test]
fn verify_named_integers() {
let nobj = NamedInteger::new(b"FOO", 0);
let bytes = nobj.to_bytes();
verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0]);
let nobj = NamedInteger::new(b"FOO", 1);
let bytes = nobj.to_bytes();
verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 1]);
let nobj = NamedInteger::new(b"FOO", 2);
let bytes = nobj.to_bytes();
verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0xa, 2]);
let nobj = NamedInteger::new(b"FOO", 0x100);
let bytes = nobj.to_bytes();
verify_expected_bytes(&bytes, &[8, b'F', b'O', b'O', b'_', 0xb, 0x00, 0x01]);
let nobj = NamedInteger::new(b"FOO", 0x10000);
let bytes = nobj.to_bytes();
verify_expected_bytes(
&bytes,
&[8, b'F', b'O', b'O', b'_', 0xc, 0x00, 0x00, 0x01, 0x00],
);
let nobj = NamedInteger::new(b"FOO", 0x100000000);
let bytes = nobj.to_bytes();
verify_expected_bytes(
&bytes,
&[
8, b'F', b'O', b'O', b'_', 0xe, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
],
);
}
#[test]
fn verify_named_string() {
let nobj = NamedString::new(b"FOO", b"hello");
let bytes = nobj.to_bytes();
verify_expected_bytes(
&bytes,
&[
8, b'F', b'O', b'O', b'_', 0xd, b'h', b'e', b'l', b'l', b'o', 0,
],
);
}
}