Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement DefMid
  • Loading branch information
IsaacWoods committed Jul 29, 2021
1 parent a883868 commit a37008d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 5 deletions.
10 changes: 6 additions & 4 deletions aml/src/lib.rs
Expand Up @@ -715,10 +715,6 @@ pub enum AmlError {
InvalidNameSeg,
InvalidPkgLength,
InvalidFieldFlags,
IncompatibleValueConversion {
current: AmlType,
target: AmlType,
},
UnterminatedStringConstant,
InvalidStringConstant,
InvalidRegionSpace(u8),
Expand Down Expand Up @@ -785,13 +781,19 @@ pub enum AmlError {
/*
* Errors produced working with AML values.
*/
IncompatibleValueConversion {
current: AmlType,
target: AmlType,
},
InvalidStatusObject,
InvalidShiftLeft,
InvalidShiftRight,
FieldRegionIsNotOpRegion,
FieldInvalidAddress,
FieldInvalidAccessSize,
TypeCannotBeCompared(AmlType),
/// Produced when the `Mid` operator is applied to a value of a type other than `Buffer` or `String`.
TypeCannotBeSliced(AmlType),
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions aml/src/opcode.rs
Expand Up @@ -59,6 +59,7 @@ pub const DEF_L_NOT_OP: u8 = 0x92;
pub const DEF_L_EQUAL_OP: u8 = 0x93;
pub const DEF_L_GREATER_OP: u8 = 0x94;
pub const DEF_L_LESS_OP: u8 = 0x95;
pub const DEF_MID_OP: u8 = 0x9e;

/*
* Miscellaneous objects
Expand Down
61 changes: 60 additions & 1 deletion aml/src/type2.rs
Expand Up @@ -18,7 +18,11 @@ use crate::{
AmlError,
DebugVerbosity,
};
use alloc::{vec, vec::Vec};
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
use core::{cmp::Ordering, convert::TryInto, mem};

/// Type 2 opcodes return a value and so can be used in expressions.
Expand Down Expand Up @@ -53,6 +57,7 @@ where
def_l_less_equal(),
def_l_not_equal(),
def_l_or(),
def_mid(),
def_package(),
def_shift_left(),
def_shift_right(),
Expand Down Expand Up @@ -390,6 +395,60 @@ where
.map(|(((), ()), result)| Ok(result))
}

fn def_mid<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
where
'c: 'a,
{
/*
* DefMid := 0x9e MidObj TermArg TermArg Target
* MidObj := TermArg => Buffer | String
*/
opcode(opcode::DEF_MID_OP)
.then(comment_scope(
DebugVerbosity::AllScopes,
"DefMid",
term_arg().then(term_arg()).then(term_arg()).then(target()).map_with_context(
|(((source, index), length), target), context| {
let index = try_with_context!(context, index.as_integer(context)) as usize;
let length = try_with_context!(context, length.as_integer(context)) as usize;

let result = try_with_context!(
context,
match source {
AmlValue::Buffer(bytes) => {
if index >= bytes.len() {
Ok(AmlValue::Buffer(vec![]))
} else if (index + length) >= bytes.len() {
Ok(AmlValue::Buffer(bytes[index..].to_vec()))
} else {
Ok(AmlValue::Buffer(bytes[index..(index + length)].to_vec()))
}
}
/*
* XXX: The spec conflates characters and bytes, so we effectively ignore unicode and do
* this bytewise, to hopefully match other implementations.
*/
AmlValue::String(string) => {
if index >= string.len() {
Ok(AmlValue::String(String::new()))
} else if (index + length) >= string.len() {
Ok(AmlValue::String(string[index..].to_string()))
} else {
Ok(AmlValue::String(string[index..(index + length)].to_string()))
}
}
_ => Err(AmlError::TypeCannotBeSliced(source.type_of())),
}
);

try_with_context!(context, context.store(target, result.clone()));
(Ok(result), context)
},
),
))
.map(|((), result)| Ok(result))
}

pub fn def_package<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
where
'c: 'a,
Expand Down

0 comments on commit a37008d

Please sign in to comment.