name_object.rs 8.7 KB

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