pkg_length.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. use crate::{
  2. parser::{take, take_n, Parser, Propagate},
  3. AmlContext,
  4. AmlError,
  5. };
  6. use bit_field::BitField;
  7. #[derive(Clone, Copy, PartialEq, Eq, Debug)]
  8. pub struct PkgLength {
  9. pub raw_length: u32,
  10. /// The offset in the structure's stream to stop parsing at - the "end" of the PkgLength. We need to track this
  11. /// instead of the actual length encoded in the PkgLength as we often need to parse some stuff between the
  12. /// PkgLength and the explicit-length structure.
  13. pub end_offset: u32,
  14. }
  15. impl PkgLength {
  16. pub fn from_raw_length(stream: &[u8], raw_length: u32) -> Result<PkgLength, AmlError> {
  17. Ok(PkgLength {
  18. raw_length,
  19. end_offset: (stream.len() as u32).checked_sub(raw_length).ok_or(AmlError::InvalidPkgLength)?,
  20. })
  21. }
  22. /// Returns `true` if the given stream is still within the structure this `PkgLength` refers
  23. /// to.
  24. pub fn still_parsing(&self, stream: &[u8]) -> bool {
  25. stream.len() as u32 > self.end_offset
  26. }
  27. }
  28. pub fn pkg_length<'a, 'c>() -> impl Parser<'a, 'c, PkgLength>
  29. where
  30. 'c: 'a,
  31. {
  32. move |input: &'a [u8], context: &'c mut AmlContext| -> crate::parser::ParseResult<'a, 'c, PkgLength> {
  33. let (new_input, context, raw_length) = raw_pkg_length().parse(input, context)?;
  34. /*
  35. * NOTE: we use the original input here, because `raw_length` includes the length of the
  36. * `PkgLength`.
  37. */
  38. match PkgLength::from_raw_length(input, raw_length) {
  39. Ok(pkg_length) => Ok((new_input, context, pkg_length)),
  40. Err(err) => Err((input, context, Propagate::Err(err))),
  41. }
  42. }
  43. }
  44. /// Parses a `PkgLength` and returns the *raw length*. If you want an instance of `PkgLength`, use
  45. /// `pkg_length` instead.
  46. pub fn raw_pkg_length<'a, 'c>() -> impl Parser<'a, 'c, u32>
  47. where
  48. 'c: 'a,
  49. {
  50. /*
  51. * PkgLength := PkgLeadByte |
  52. * <PkgLeadByte ByteData> |
  53. * <PkgLeadByte ByteData ByteData> |
  54. * <PkgLeadByte ByteData ByteData ByteData>
  55. *
  56. * The length encoded by the PkgLength includes the number of bytes used to encode it.
  57. */
  58. move |input: &'a [u8], context: &'c mut AmlContext| {
  59. let (new_input, context, lead_byte) = take().parse(input, context)?;
  60. let byte_count = lead_byte.get_bits(6..8);
  61. if byte_count == 0 {
  62. let length = u32::from(lead_byte.get_bits(0..6));
  63. return Ok((new_input, context, length));
  64. }
  65. let (new_input, context, length): (&[u8], &mut AmlContext, u32) = match take_n(byte_count as u32)
  66. .parse(new_input, context)
  67. {
  68. Ok((new_input, context, bytes)) => {
  69. let initial_length = u32::from(lead_byte.get_bits(0..4));
  70. (
  71. new_input,
  72. context,
  73. bytes
  74. .iter()
  75. .enumerate()
  76. .fold(initial_length, |length, (i, &byte)| length + (u32::from(byte) << (4 + i * 8))),
  77. )
  78. }
  79. /*
  80. * The stream was too short. We return an error, making sure to return the
  81. * *original* stream (that we haven't consumed any of).
  82. */
  83. Err((_, context, _)) => return Err((input, context, Propagate::Err(AmlError::UnexpectedEndOfStream))),
  84. };
  85. Ok((new_input, context, length))
  86. }
  87. }
  88. #[cfg(test)]
  89. mod tests {
  90. use super::*;
  91. use crate::{test_utils::*, AmlError};
  92. fn test_correct_pkglength(stream: &[u8], expected_raw_length: u32, expected_leftover: &[u8]) {
  93. let mut context = make_test_context();
  94. check_ok!(
  95. pkg_length().parse(stream, &mut context),
  96. PkgLength::from_raw_length(stream, expected_raw_length).unwrap(),
  97. &expected_leftover
  98. );
  99. }
  100. #[test]
  101. fn test_raw_pkg_length() {
  102. let mut context = make_test_context();
  103. check_ok!(raw_pkg_length().parse(&[0b01000101, 0x14], &mut context), 325, &[]);
  104. check_ok!(raw_pkg_length().parse(&[0b01000111, 0x14, 0x46], &mut context), 327, &[0x46]);
  105. check_ok!(raw_pkg_length().parse(&[0b10000111, 0x14, 0x46], &mut context), 287047, &[]);
  106. }
  107. #[test]
  108. fn test_pkg_length() {
  109. let mut context = make_test_context();
  110. check_err!(pkg_length().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
  111. test_correct_pkglength(&[0x00], 0, &[]);
  112. test_correct_pkglength(&[0x05, 0xf5, 0x7f, 0x3e, 0x54, 0x03], 5, &[0xf5, 0x7f, 0x3e, 0x54, 0x03]);
  113. check_ok!(
  114. pkg_length()
  115. .feed(|length| crate::parser::take_to_end_of_pkglength(length))
  116. .parse(&[0x05, 0x01, 0x02, 0x03, 0x04, 0xff, 0xff, 0xff], &mut context),
  117. &[0x01, 0x02, 0x03, 0x04],
  118. &[0xff, 0xff, 0xff]
  119. );
  120. }
  121. #[test]
  122. fn not_enough_pkglength() {
  123. let mut context = make_test_context();
  124. check_err!(
  125. pkg_length().parse(&[0b11000000, 0xff, 0x4f], &mut context),
  126. AmlError::UnexpectedEndOfStream,
  127. &[0b11000000, 0xff, 0x4f]
  128. );
  129. }
  130. #[test]
  131. fn not_enough_stream() {
  132. let mut context = make_test_context();
  133. check_err!(pkg_length().parse(&[0x05, 0xf5], &mut context), AmlError::InvalidPkgLength, &[0x05, 0xf5]);
  134. }
  135. }