2
0

name_object.rs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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(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(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().map(|path| Ok(AmlName(path))).parse(input, context),
  95. }
  96. })
  97. }
  98. pub fn name_path<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  99. where
  100. 'c: 'a,
  101. {
  102. /*
  103. * NamePath := NullName | DualNamePath | MultiNamePath | NameSeg
  104. */
  105. choice!(
  106. null_name(),
  107. dual_name_path(),
  108. multi_name_path(),
  109. name_seg().map(|seg| Ok(alloc::vec![NameComponent::Segment(seg)]))
  110. )
  111. }
  112. pub fn null_name<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  113. where
  114. 'c: 'a,
  115. {
  116. /*
  117. * NullName := 0x00
  118. *
  119. * This doesn't actually allocate because the `Vec`'s capacity is zero.
  120. */
  121. opcode(NULL_NAME).map(|_| Ok(Vec::with_capacity(0)))
  122. }
  123. pub fn dual_name_path<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  124. where
  125. 'c: 'a,
  126. {
  127. /*
  128. * DualNamePath := 0x2e NameSeg NameSeg
  129. */
  130. opcode(DUAL_NAME_PREFIX).then(name_seg()).then(name_seg()).map(|(((), first), second)| {
  131. Ok(alloc::vec![NameComponent::Segment(first), NameComponent::Segment(second)])
  132. })
  133. }
  134. pub fn multi_name_path<'a, 'c>() -> impl Parser<'a, 'c, Vec<NameComponent>>
  135. where
  136. 'c: 'a,
  137. {
  138. /*
  139. * MultiNamePath := 0x2f ByteData{SegCount} NameSeg(SegCount)
  140. */
  141. move |input, context| {
  142. let (new_input, context, ((), seg_count)) =
  143. opcode(MULTI_NAME_PREFIX).then(take()).parse(input, context)?;
  144. match n_of(name_seg(), usize::from(seg_count)).parse(new_input, context) {
  145. Ok((new_input, context, name_segs)) => {
  146. Ok((new_input, context, name_segs.iter().map(|&seg| NameComponent::Segment(seg)).collect()))
  147. }
  148. // Correct returned input to the one we haven't touched
  149. Err((_, context, err)) => Err((input, context, err)),
  150. }
  151. }
  152. }
  153. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
  154. pub struct NameSeg(pub(crate) [u8; 4]);
  155. impl NameSeg {
  156. pub(crate) fn from_str(string: &str) -> Result<NameSeg, AmlError> {
  157. // Each NameSeg can only have four chars, and must have at least one
  158. if string.len() < 1 || string.len() > 4 {
  159. return Err(AmlError::InvalidNameSeg);
  160. }
  161. // We pre-fill the array with '_', so it will already be correct if the length is < 4
  162. let mut seg = [b'_'; 4];
  163. let bytes = string.as_bytes();
  164. // Manually do the first one, because we have to check it's a LeadNameChar
  165. if !is_lead_name_char(bytes[0]) {
  166. return Err(AmlError::InvalidNameSeg);
  167. }
  168. seg[0] = bytes[0];
  169. // Copy the rest of the chars, checking that they're NameChars
  170. for i in 1..bytes.len() {
  171. if !is_name_char(bytes[i]) {
  172. return Err(AmlError::InvalidNameSeg);
  173. }
  174. seg[i] = bytes[i];
  175. }
  176. Ok(NameSeg(seg))
  177. }
  178. /// Turn a `NameSeg` into a `&str`. Returns it in a `ParseResult` so it's easy to use from
  179. /// inside parsers.
  180. pub fn as_str(&self) -> &str {
  181. /*
  182. * This is safe, because we always check that all the bytes are valid ASCII, so every
  183. * `NameSeg` will be valid UTF8.
  184. */
  185. unsafe { str::from_utf8_unchecked(&self.0) }
  186. }
  187. }
  188. // A list of ASCII codes is pretty much never useful, so we always just show it as a string
  189. impl fmt::Debug for NameSeg {
  190. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  191. write!(f, "{:?}", self.as_str())
  192. }
  193. }
  194. pub fn name_seg<'a, 'c>() -> impl Parser<'a, 'c, NameSeg>
  195. where
  196. 'c: 'a,
  197. {
  198. /*
  199. * NameSeg := <LeadNameChar NameChar NameChar NameChar>
  200. */
  201. // TODO: can we write this better?
  202. move |input, context: &'c mut AmlContext| {
  203. let (input, context, char_1) = consume(is_lead_name_char).parse(input, context)?;
  204. let (input, context, char_2) = consume(is_name_char).parse(input, context)?;
  205. let (input, context, char_3) = consume(is_name_char).parse(input, context)?;
  206. let (input, context, char_4) = consume(is_name_char).parse(input, context)?;
  207. Ok((input, context, NameSeg([char_1, char_2, char_3, char_4])))
  208. }
  209. }
  210. fn is_lead_name_char(byte: u8) -> bool {
  211. (byte >= b'A' && byte <= b'Z') || byte == b'_'
  212. }
  213. fn is_digit_char(byte: u8) -> bool {
  214. byte >= b'0' && byte <= b'9'
  215. }
  216. fn is_name_char(byte: u8) -> bool {
  217. is_lead_name_char(byte) || is_digit_char(byte)
  218. }
  219. #[cfg(test)]
  220. mod tests {
  221. use super::*;
  222. use crate::{parser::Parser, test_utils::*, AmlError};
  223. #[test]
  224. fn test_name_seg() {
  225. let mut context = crate::test_utils::make_test_context();
  226. check_ok!(
  227. name_seg().parse(&[b'A', b'F', b'3', b'Z'], &mut context),
  228. NameSeg([b'A', b'F', b'3', b'Z']),
  229. &[]
  230. );
  231. check_ok!(
  232. name_seg().parse(&[b'A', b'F', b'3', b'Z', 0xff], &mut context),
  233. NameSeg([b'A', b'F', b'3', b'Z']),
  234. &[0xff]
  235. );
  236. check_err!(
  237. name_seg().parse(&[0xff, b'E', b'A', b'7'], &mut context),
  238. AmlError::UnexpectedByte(0xff),
  239. &[0xff, b'E', b'A', b'7']
  240. );
  241. check_err!(name_seg().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
  242. }
  243. #[test]
  244. fn test_name_path() {
  245. let mut context = crate::test_utils::make_test_context();
  246. check_err!(name_path().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
  247. check_ok!(name_path().parse(&[0x00], &mut context), alloc::vec![], &[]);
  248. check_ok!(name_path().parse(&[0x00, 0x00], &mut context), alloc::vec![], &[0x00]);
  249. check_err!(name_path().parse(&[0x2e, b'A'], &mut context), AmlError::UnexpectedEndOfStream, &[0x2e, b'A']);
  250. check_ok!(
  251. name_path().parse(&[0x2e, b'A', b'B', b'C', b'D', b'E', b'_', b'F', b'G'], &mut context),
  252. alloc::vec![
  253. NameComponent::Segment(NameSeg([b'A', b'B', b'C', b'D'])),
  254. NameComponent::Segment(NameSeg([b'E', b'_', b'F', b'G']))
  255. ],
  256. &[]
  257. );
  258. }
  259. #[test]
  260. fn test_prefix_path() {
  261. let mut context = crate::test_utils::make_test_context();
  262. check_ok!(
  263. name_string().parse(&[b'^', b'A', b'B', b'C', b'D'], &mut context),
  264. AmlName::from_str("^ABCD").unwrap(),
  265. &[]
  266. );
  267. check_ok!(
  268. name_string().parse(&[b'^', b'^', b'^', b'A', b'B', b'C', b'D'], &mut context),
  269. AmlName::from_str("^^^ABCD").unwrap(),
  270. &[]
  271. );
  272. }
  273. }