name_object.rs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. use crate::{
  2. misc::{arg_obj, debug_obj, local_obj, ArgNum, LocalNum},
  3. namespace::{AmlName, NameComponent},
  4. opcode::{opcode, DUAL_NAME_PREFIX, MULTI_NAME_PREFIX, NULL_NAME, PREFIX_CHAR, ROOT_CHAR},
  5. parser::{choice, comment_scope, consume, n_of, take, take_while, Parser},
  6. AmlContext,
  7. AmlError,
  8. DebugVerbosity,
  9. };
  10. use alloc::vec::Vec;
  11. use core::{fmt, str};
  12. /// Produced by the `Target`, `SimpleName`, and `SuperName` parsers
  13. #[derive(Clone, Debug)]
  14. pub enum Target {
  15. Name(AmlName),
  16. Debug,
  17. Arg(ArgNum),
  18. Local(LocalNum),
  19. }
  20. pub fn super_name<'a, 'c>() -> impl Parser<'a, 'c, Target>
  21. where
  22. 'c: 'a,
  23. {
  24. /*
  25. * SuperName := SimpleName | DebugObj | Type6Opcode
  26. * TODO: this doesn't cover Type6Opcode yet
  27. */
  28. comment_scope(
  29. DebugVerbosity::AllScopes,
  30. "SuperName",
  31. choice!(debug_obj().map(|()| Ok(Target::Debug)), simple_name()),
  32. )
  33. }
  34. pub fn simple_name<'a, 'c>() -> impl Parser<'a, 'c, Target>
  35. where
  36. 'c: 'a,
  37. {
  38. /*
  39. * SimpleName := NameString | ArgObj | LocalObj
  40. */
  41. comment_scope(
  42. DebugVerbosity::AllScopes,
  43. "SimpleName",
  44. choice!(
  45. name_string().map(move |name| Ok(Target::Name(name))),
  46. arg_obj().map(|arg_num| Ok(Target::Arg(arg_num))),
  47. local_obj().map(|local_num| Ok(Target::Local(local_num)))
  48. ),
  49. )
  50. }
  51. pub fn name_string<'a, 'c>() -> impl Parser<'a, 'c, AmlName>
  52. where
  53. 'c: 'a,
  54. {
  55. /*
  56. * NameString := <RootChar('\') NamePath> | <PrefixPath NamePath>
  57. * PrefixPath := Nothing | <'^' PrefixPath>
  58. */
  59. let root_name_string = opcode(ROOT_CHAR).then(name_path()).map(|((), ref name_path)| {
  60. let mut name = alloc::vec![NameComponent::Root];
  61. name.extend_from_slice(name_path);
  62. Ok(AmlName(name))
  63. });
  64. let prefix_path =
  65. take_while(opcode(PREFIX_CHAR)).then(name_path()).map(|(num_prefix_chars, ref name_path)| {
  66. let mut name = alloc::vec![NameComponent::Prefix; num_prefix_chars];
  67. name.extend_from_slice(name_path);
  68. Ok(AmlName(name))
  69. });
  70. // TODO: combinator to select a parser based on a peeked byte?
  71. comment_scope(DebugVerbosity::AllScopes, "NameString", move |input: &'a [u8], context| {
  72. let first_char = match input.first() {
  73. Some(&c) => c,
  74. None => return Err((input, context, AmlError::UnexpectedEndOfStream)),
  75. };
  76. match first_char {
  77. ROOT_CHAR => root_name_string.parse(input, context),
  78. PREFIX_CHAR => prefix_path.parse(input, context),
  79. _ => name_path().map(|path| Ok(AmlName(path))).parse(input, context),
  80. }
  81. })
  82. }
  83. pub fn name_path<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  84. where
  85. 'c: 'a,
  86. {
  87. /*
  88. * NamePath := NullName | DualNamePath | MultiNamePath | NameSeg
  89. */
  90. choice!(
  91. null_name(),
  92. dual_name_path(),
  93. multi_name_path(),
  94. name_seg().map(|seg| Ok(alloc::vec![NameComponent::Segment(seg)]))
  95. )
  96. }
  97. pub fn null_name<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  98. where
  99. 'c: 'a,
  100. {
  101. /*
  102. * NullName := 0x00
  103. *
  104. * This doesn't actually allocate because the `Vec`'s capacity is zero.
  105. */
  106. opcode(NULL_NAME).map(|_| Ok(Vec::with_capacity(0)))
  107. }
  108. pub fn dual_name_path<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  109. where
  110. 'c: 'a,
  111. {
  112. /*
  113. * DualNamePath := 0x2e NameSeg NameSeg
  114. */
  115. opcode(DUAL_NAME_PREFIX).then(name_seg()).then(name_seg()).map(|(((), first), second)| {
  116. Ok(alloc::vec![NameComponent::Segment(first), NameComponent::Segment(second)])
  117. })
  118. }
  119. pub fn multi_name_path<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  120. where
  121. 'c: 'a,
  122. {
  123. /*
  124. * MultiNamePath := 0x2f ByteData{SegCount} NameSeg(SegCount)
  125. */
  126. move |input, context| {
  127. let (new_input, context, ((), seg_count)) =
  128. opcode(MULTI_NAME_PREFIX).then(take()).parse(input, context)?;
  129. match n_of(name_seg(), usize::from(seg_count)).parse(new_input, context) {
  130. Ok((new_input, context, name_segs)) => {
  131. Ok((new_input, context, name_segs.iter().map(|&seg| NameComponent::Segment(seg)).collect()))
  132. }
  133. // Correct returned input to the one we haven't touched
  134. Err((_, context, err)) => Err((input, context, err)),
  135. }
  136. }
  137. }
  138. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
  139. pub struct NameSeg(pub(crate) [u8; 4]);
  140. impl NameSeg {
  141. pub(crate) fn from_str(string: &str) -> Result<NameSeg, AmlError> {
  142. // Each NameSeg can only have four chars, and must have at least one
  143. if string.len() < 1 || string.len() > 4 {
  144. return Err(AmlError::InvalidNameSeg);
  145. }
  146. // We pre-fill the array with '_', so it will already be correct if the length is < 4
  147. let mut seg = [b'_'; 4];
  148. let bytes = string.as_bytes();
  149. // Manually do the first one, because we have to check it's a LeadNameChar
  150. if !is_lead_name_char(bytes[0]) {
  151. return Err(AmlError::InvalidNameSeg);
  152. }
  153. seg[0] = bytes[0];
  154. // Copy the rest of the chars, checking that they're NameChars
  155. for i in 1..bytes.len() {
  156. if !is_name_char(bytes[i]) {
  157. return Err(AmlError::InvalidNameSeg);
  158. }
  159. seg[i] = bytes[i];
  160. }
  161. Ok(NameSeg(seg))
  162. }
  163. /// Turn a `NameSeg` into a `&str`. Returns it in a `ParseResult` so it's easy to use from
  164. /// inside parsers.
  165. pub fn as_str(&self) -> &str {
  166. /*
  167. * This is safe, because we always check that all the bytes are valid ASCII, so every
  168. * `NameSeg` will be valid UTF8.
  169. */
  170. unsafe { str::from_utf8_unchecked(&self.0) }
  171. }
  172. }
  173. // A list of ASCII codes is pretty much never useful, so we always just show it as a string
  174. impl fmt::Debug for NameSeg {
  175. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  176. write!(f, "{:?}", self.as_str())
  177. }
  178. }
  179. pub fn name_seg<'a, 'c>() -> impl Parser<'a, 'c, NameSeg>
  180. where
  181. 'c: 'a,
  182. {
  183. /*
  184. * NameSeg := <LeadNameChar NameChar NameChar NameChar>
  185. */
  186. // TODO: can we write this better?
  187. move |input, context: &'c mut AmlContext| {
  188. let (input, context, char_1) = consume(is_lead_name_char).parse(input, context)?;
  189. let (input, context, char_2) = consume(is_name_char).parse(input, context)?;
  190. let (input, context, char_3) = consume(is_name_char).parse(input, context)?;
  191. let (input, context, char_4) = consume(is_name_char).parse(input, context)?;
  192. Ok((input, context, NameSeg([char_1, char_2, char_3, char_4])))
  193. }
  194. }
  195. fn is_lead_name_char(byte: u8) -> bool {
  196. (byte >= b'A' && byte <= b'Z') || byte == b'_'
  197. }
  198. fn is_digit_char(byte: u8) -> bool {
  199. byte >= b'0' && byte <= b'9'
  200. }
  201. fn is_name_char(byte: u8) -> bool {
  202. is_lead_name_char(byte) || is_digit_char(byte)
  203. }
  204. #[cfg(test)]
  205. mod tests {
  206. use super::*;
  207. use crate::{parser::Parser, test_utils::*, AmlContext, AmlError, DebugVerbosity};
  208. #[test]
  209. fn test_name_seg() {
  210. let mut context = AmlContext::new(false, DebugVerbosity::None);
  211. check_ok!(
  212. name_seg().parse(&[b'A', b'F', b'3', b'Z'], &mut context),
  213. NameSeg([b'A', b'F', b'3', b'Z']),
  214. &[]
  215. );
  216. check_ok!(
  217. name_seg().parse(&[b'A', b'F', b'3', b'Z', 0xff], &mut context),
  218. NameSeg([b'A', b'F', b'3', b'Z']),
  219. &[0xff]
  220. );
  221. check_err!(
  222. name_seg().parse(&[0xff, b'E', b'A', b'7'], &mut context),
  223. AmlError::UnexpectedByte(0xff),
  224. &[0xff, b'E', b'A', b'7']
  225. );
  226. check_err!(name_seg().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
  227. }
  228. #[test]
  229. fn test_name_path() {
  230. let mut context = AmlContext::new(false, DebugVerbosity::None);
  231. check_err!(name_path().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
  232. check_ok!(name_path().parse(&[0x00], &mut context), alloc::vec![], &[]);
  233. check_ok!(name_path().parse(&[0x00, 0x00], &mut context), alloc::vec![], &[0x00]);
  234. check_err!(name_path().parse(&[0x2e, b'A'], &mut context), AmlError::UnexpectedEndOfStream, &[0x2e, b'A']);
  235. check_ok!(
  236. name_path().parse(&[0x2e, b'A', b'B', b'C', b'D', b'E', b'_', b'F', b'G'], &mut context),
  237. alloc::vec![
  238. NameComponent::Segment(NameSeg([b'A', b'B', b'C', b'D'])),
  239. NameComponent::Segment(NameSeg([b'E', b'_', b'F', b'G']))
  240. ],
  241. &[]
  242. );
  243. }
  244. #[test]
  245. fn test_prefix_path() {
  246. let mut context = AmlContext::new(false, DebugVerbosity::None);
  247. check_ok!(
  248. name_string().parse(&[b'^', b'A', b'B', b'C', b'D'], &mut context),
  249. AmlName::from_str("^ABCD").unwrap(),
  250. &[]
  251. );
  252. check_ok!(
  253. name_string().parse(&[b'^', b'^', b'^', b'A', b'B', b'C', b'D'], &mut context),
  254. AmlName::from_str("^^^ABCD").unwrap(),
  255. &[]
  256. );
  257. }
  258. }