pkg_length.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. use crate::{
  2. parser::{take, take_n, Parser},
  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 distance from the end of the structure this `PkgLength` refers to, and the end of the
  11. /// stream.
  12. pub end_offset: u32,
  13. }
  14. impl PkgLength {
  15. pub fn from_raw_length(stream: &[u8], raw_length: u32) -> PkgLength {
  16. PkgLength { raw_length, end_offset: stream.len() as u32 - raw_length }
  17. }
  18. /// Returns `true` if the given stream is still within the structure this `PkgLength` refers
  19. /// to.
  20. pub fn still_parsing(&self, stream: &[u8]) -> bool {
  21. stream.len() as u32 > self.end_offset
  22. }
  23. }
  24. pub fn pkg_length<'a, 'c>() -> impl Parser<'a, 'c, PkgLength>
  25. where
  26. 'c: 'a,
  27. {
  28. move |input: &'a [u8], context: &'c mut AmlContext| {
  29. let (new_input, context, raw_length) = raw_pkg_length().parse(input, context)?;
  30. /*
  31. * NOTE: we use the original input here, because `raw_length` includes the length of the
  32. * `PkgLength`.
  33. */
  34. Ok((new_input, context, PkgLength::from_raw_length(input, raw_length)))
  35. }
  36. }
  37. /// Parses a `PkgLength` and returns the *raw length*. If you want an instance of `PkgLength`, use
  38. /// `pkg_length` instead.
  39. pub fn raw_pkg_length<'a, 'c>() -> impl Parser<'a, 'c, u32>
  40. where
  41. 'c: 'a,
  42. {
  43. /*
  44. * PkgLength := PkgLeadByte |
  45. * <PkgLeadByte ByteData> |
  46. * <PkgLeadByte ByteData ByteData> |
  47. * <PkgLeadByte ByteData ByteData ByteData>
  48. *
  49. * The length encoded by the PkgLength includes the number of bytes used to encode it.
  50. */
  51. move |input: &'a [u8], context: &'c mut AmlContext| {
  52. let (new_input, context, lead_byte) = take().parse(input, context)?;
  53. let byte_count = lead_byte.get_bits(6..8);
  54. if byte_count == 0 {
  55. let length = u32::from(lead_byte.get_bits(0..6));
  56. return Ok((new_input, context, length));
  57. }
  58. let (new_input, context, length): (&[u8], &mut AmlContext, u32) =
  59. match take_n(byte_count as u32).parse(new_input, context) {
  60. Ok((new_input, context, bytes)) => {
  61. let initial_length = u32::from(lead_byte.get_bits(0..4));
  62. (
  63. new_input,
  64. context,
  65. bytes
  66. .iter()
  67. .enumerate()
  68. .fold(initial_length, |length, (i, &byte)| length + (u32::from(byte) << (4 + i * 8))),
  69. )
  70. }
  71. /*
  72. * The stream was too short. We return an error, making sure to return the
  73. * *original* stream (that we haven't consumed any of).
  74. */
  75. Err((_, context, _)) => return Err((input, context, AmlError::UnexpectedEndOfStream)),
  76. };
  77. Ok((new_input, context, length))
  78. }
  79. }
  80. #[cfg(test)]
  81. mod tests {
  82. use super::*;
  83. use crate::{test_utils::*, AmlError};
  84. fn test_correct_pkglength(stream: &[u8], expected_raw_length: u32, expected_leftover: &[u8]) {
  85. let mut context = AmlContext::new();
  86. check_ok!(
  87. pkg_length().parse(stream, &mut context),
  88. PkgLength::from_raw_length(stream, expected_raw_length),
  89. &expected_leftover
  90. );
  91. }
  92. #[test]
  93. fn test_raw_pkg_length() {
  94. let mut context = AmlContext::new();
  95. check_ok!(raw_pkg_length().parse(&[0b01000101, 0x14], &mut context), 325, &[]);
  96. check_ok!(raw_pkg_length().parse(&[0b01000111, 0x14, 0x46], &mut context), 327, &[0x46]);
  97. check_ok!(raw_pkg_length().parse(&[0b10000111, 0x14, 0x46], &mut context), 287047, &[]);
  98. }
  99. #[test]
  100. fn test_pkg_length() {
  101. let mut context = AmlContext::new();
  102. check_err!(pkg_length().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
  103. test_correct_pkglength(&[0x00], 0, &[]);
  104. test_correct_pkglength(&[0x05, 0xf5, 0x7f, 0x3e, 0x54, 0x03], 5, &[0xf5, 0x7f, 0x3e, 0x54, 0x03]);
  105. check_err!(
  106. pkg_length().parse(&[0b11000000, 0xff, 0x4f], &mut context),
  107. AmlError::UnexpectedEndOfStream,
  108. &[0b11000000, 0xff, 0x4f]
  109. );
  110. }
  111. #[test]
  112. #[should_panic]
  113. fn not_enough_stream() {
  114. /*
  115. * TODO: Ideally, this shouldn't panic the parser, but return a `UnexpectedEndOfStream`.
  116. */
  117. test_correct_pkglength(&[0x05, 0xf5], 5, &[0xf5]);
  118. }
  119. }