name_object.rs 9.4 KB

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