You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

686 lines
24 KiB

  1. // TODO: try less hard, just mem::transmute all this junk away
  2. // TODO: PSOPacketData derive
  3. #![recursion_limit="256"]
  4. extern crate proc_macro;
  5. use proc_macro::TokenStream;
  6. use syn::{parse_macro_input, ItemStruct, NestedMeta, DeriveInput, Field};
  7. use syn::punctuated::Iter;
  8. use quote::quote;
  9. #[derive(Debug, PartialEq)]
  10. enum AttrMeta {
  11. None,
  12. Utf8,
  13. Utf16,
  14. NoDebug,
  15. LengthIs(syn::Ident),
  16. LengthOf(syn::Ident),
  17. }
  18. #[derive(Debug)]
  19. enum AttrType {
  20. Value(syn::TypePath, syn::Ident, AttrMeta),
  21. Array(syn::TypePath, syn::Ident, usize, AttrMeta)
  22. }
  23. fn generate_struct_def(name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
  24. let mut struct_def = Vec::new();
  25. for attr in attrs {
  26. let element = match attr {
  27. AttrType::Value(ty, name, _) => {
  28. quote!(pub #name: #ty)
  29. },
  30. AttrType::Array(ty, name, len, _) => {
  31. quote!(pub #name: [#ty; #len])
  32. }
  33. };
  34. struct_def.push(element);
  35. }
  36. quote! {
  37. pub struct #name {
  38. #(#struct_def),*
  39. }
  40. }
  41. }
  42. fn generate_from_bytes(attrs: &Vec<AttrType>) -> Vec<proc_macro2::TokenStream> {
  43. let mut from_bytes = Vec::new();
  44. for attr in attrs {
  45. let element = match attr {
  46. AttrType::Value(ty, name, _) => {
  47. let type_str = ty.path.segments[0].ident.to_string();
  48. if type_str == "Vec" {
  49. let vec_type = match &ty.path.segments[0].arguments {
  50. syn::PathArguments::AngleBracketed(arg) => {
  51. match &arg.args[0] {
  52. syn::GenericArgument::Type(typ) => {
  53. match &typ {
  54. syn::Type::Path(path) => {
  55. Some(path.path.segments[0].ident.clone())
  56. }
  57. _ => None
  58. }
  59. }
  60. _ => None,
  61. }
  62. }
  63. _ => None
  64. }.unwrap();
  65. quote! {
  66. #name: {
  67. let mut tmp = Vec::new();
  68. for _ in 0..flag {
  69. tmp.push(<#vec_type as PSOPacketData>::from_bytes(&mut cur)?);
  70. }
  71. tmp
  72. }
  73. }
  74. }
  75. else {
  76. quote! {
  77. #name: <#ty as PSOPacketData>::from_bytes(&mut cur)?,
  78. }
  79. }
  80. },
  81. AttrType::Array(ty, name, len, _) => {
  82. quote! {
  83. #name: {
  84. let mut arr = [#ty::default(); #len];
  85. for e in arr.iter_mut() {
  86. *e = #ty::from_bytes(&mut cur)?
  87. }
  88. arr
  89. },
  90. }
  91. }
  92. };
  93. from_bytes.push(element);
  94. }
  95. from_bytes
  96. }
  97. fn generate_as_bytes(attrs: &Vec<AttrType>) -> Vec<proc_macro2::TokenStream> {
  98. let mut as_bytes = Vec::new();
  99. for attr in attrs {
  100. let element = match attr {
  101. AttrType::Value(ty, name, _) => {
  102. let type_str = ty.path.segments[0].ident.to_string();
  103. if type_str == "Vec" {
  104. quote! {
  105. flag = self.#name.len() as u32;
  106. for i in self.#name.iter() {
  107. buf.extend_from_slice(&PSOPacketData::as_bytes(i));
  108. }
  109. }
  110. }
  111. else {
  112. quote! {
  113. buf.extend_from_slice(&PSOPacketData::as_bytes(&self.#name));
  114. }
  115. }
  116. },
  117. AttrType::Array(_ty, name, len, _) => {
  118. quote! {
  119. for i in 0..#len {
  120. buf.extend_from_slice(&self.#name[i].as_bytes());
  121. }
  122. }
  123. }
  124. };
  125. as_bytes.push(element);
  126. }
  127. as_bytes
  128. }
  129. fn generate_psopacket_impl(pkt_cmd: u16, name: syn::Ident, attrs: &Vec<AttrType>, include_flag: bool) -> proc_macro2::TokenStream {
  130. let from_bytes = generate_from_bytes(&attrs);
  131. let as_bytes = generate_as_bytes(&attrs);
  132. quote! {
  133. impl PSOPacket for #name {
  134. fn from_bytes(data: &[u8]) -> Result<#name, PacketParseError> {
  135. let mut cur = std::io::Cursor::new(data);
  136. let mut b: [u8; 2] = [0; 2];
  137. cur.read(&mut b).unwrap();
  138. let len = u16::from_le_bytes(b);
  139. cur.read(&mut b).unwrap();
  140. let cmd = u16::from_le_bytes(b);
  141. let mut f: [u8; 4] = [0; 4];
  142. let flag = if #include_flag {
  143. cur.read(&mut f).unwrap();
  144. u32::from_le_bytes(f)
  145. }
  146. else { 0 };
  147. if cmd != #pkt_cmd {
  148. return Err(PacketParseError::WrongPacketCommand {expected: #pkt_cmd, got: cmd});
  149. }
  150. if len as usize != data.len() {
  151. return Err(PacketParseError::WrongPacketSize(len, data.len()));
  152. }
  153. let result = Ok(#name {
  154. #(#from_bytes)*
  155. });
  156. if cur.position() as usize != data.len() {
  157. return Err(PacketParseError::DataStructNotLargeEnough(cur.position(), data.len()));
  158. }
  159. result
  160. }
  161. fn as_bytes(&self) -> Vec<u8> {
  162. let mut buf = Vec::new();
  163. let mut flag = 0;
  164. #(#as_bytes)*
  165. while buf.len() % 4 != 0 {
  166. buf.push(0);
  167. }
  168. let pkt_len = (buf.len() + if #include_flag { 8 } else { 4 }) as u16;
  169. let mut prebuf: Vec<u8> = Vec::new();
  170. prebuf.extend_from_slice(&u16::to_le_bytes(pkt_len));
  171. prebuf.extend_from_slice(&u16::to_le_bytes(#pkt_cmd));
  172. if #include_flag {
  173. prebuf.extend_from_slice(&u32::to_le_bytes(flag));
  174. }
  175. prebuf.append(&mut buf);
  176. prebuf
  177. }
  178. }
  179. }
  180. }
  181. fn generate_debug_impl(name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
  182. let dbg_write = attrs
  183. .iter()
  184. .map(|attr| {
  185. match attr {
  186. AttrType::Value(ty, name, meta) => {
  187. let ident_str = name.to_string();
  188. let type_str = ty.path.segments[0].ident.to_string();
  189. match meta {
  190. AttrMeta::NoDebug => quote! {
  191. .field(&format!("{} [{}]", #ident_str, #type_str), &format_args!("[...]"))
  192. },
  193. _ => quote! {
  194. .field(&format!("{} [{}]", #ident_str, #type_str), &self.#name)
  195. }
  196. }
  197. },
  198. AttrType::Array(ty, name, len, meta) => {
  199. let ident_str = name.to_string();
  200. let type_str = ty.path.segments[0].ident.to_string();
  201. match meta {
  202. AttrMeta::Utf8 => quote! {
  203. .field(&format!("{} [utf8; {}]", #ident_str, #len),
  204. match std::str::from_utf8(&self.#name) {
  205. Ok(ref s) => s,
  206. Err(_) => &self.#name
  207. })
  208. },
  209. AttrMeta::Utf16 => quote! {
  210. .field(&format!("{} [utf16; {}]", #ident_str, #len),
  211. match std::str::from_utf16(&self.#name) {
  212. Ok(ref s) => s,
  213. Err(_) => &self.#name
  214. })
  215. },
  216. AttrMeta::NoDebug => quote! {
  217. .field(&format!("{} [{}; {}]", #ident_str, #type_str, #len), &format_args!("[...]"))
  218. },
  219. _ => quote! {
  220. .field(&format!("{} [{}; {}]", #ident_str, #type_str, #len), &format_args!("{:?}", &self.#name))
  221. }
  222. }
  223. }
  224. }
  225. })
  226. .collect::<Vec<_>>();
  227. let name_str = name.to_string();
  228. quote! {
  229. impl std::fmt::Debug for #name {
  230. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  231. f.debug_struct(#name_str)
  232. #(#dbg_write)*
  233. .finish()
  234. }
  235. }
  236. }
  237. }
  238. fn generate_partialeq_impl(name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
  239. let mut partialeq = Vec::new();
  240. for attr in attrs {
  241. let element = match attr {
  242. AttrType::Value(_, name, _) => {
  243. quote! {
  244. if self.#name!= other.#name {
  245. return false;
  246. }
  247. }
  248. },
  249. AttrType::Array(_, name, _, _) => {
  250. quote! {
  251. if self.#name[..] != other.#name[..] {
  252. return false;
  253. }
  254. }
  255. }
  256. };
  257. partialeq.push(element);
  258. }
  259. quote! {
  260. impl std::cmp::PartialEq for #name {
  261. fn eq(&self, other: &Self) -> bool {
  262. #(#partialeq)*
  263. true
  264. }
  265. }
  266. }
  267. }
  268. fn get_struct_fields(fields: Iter<Field>) -> Result<Vec<AttrType>, TokenStream> {
  269. let mut attrs = Vec::new();
  270. let mut must_be_last = false;
  271. for field in fields {
  272. if must_be_last {
  273. return Err(syn::Error::new(field.ident.as_ref().unwrap().span(), "variables can not follow Vec or String").to_compile_error().into());
  274. }
  275. let mut attr_meta = AttrMeta::None;
  276. for attr in &field.attrs {
  277. attr_meta = match attr.path.segments[0].ident.to_string().as_str() {
  278. "utf8" => AttrMeta::Utf8,
  279. "utf16" => AttrMeta::Utf16,
  280. "nodebug" => AttrMeta::NoDebug,
  281. "length_is" => AttrMeta::LengthIs(attr.parse_args::<syn::Ident>().unwrap()),
  282. "length_of" => AttrMeta::LengthOf(attr.parse_args::<syn::Ident>().unwrap()),
  283. _ => AttrMeta::None
  284. }
  285. }
  286. match &field.ty {
  287. syn::Type::Array(ty) => {
  288. if let (syn::Type::Path(ref ty), syn::Expr::Lit(ref lit)) = (&*ty.elem, &ty.len) {
  289. if let syn::Lit::Int(ref int) = lit.lit {
  290. attrs.push(AttrType::Array(ty.clone(),
  291. field.ident.as_ref().unwrap().clone(),
  292. int.base10_parse().unwrap(),
  293. attr_meta
  294. ))
  295. }
  296. }
  297. },
  298. syn::Type::Path(ty) => {
  299. let type_str = ty.path.segments[0].ident.to_string();
  300. if type_str == "String" || type_str == "Vec"{
  301. must_be_last = true;
  302. }
  303. attrs.push(AttrType::Value(ty.clone(),
  304. field.ident.as_ref().unwrap().clone(),
  305. attr_meta))
  306. },
  307. _ => {}
  308. }
  309. }
  310. Ok(attrs)
  311. }
  312. #[proc_macro_attribute]
  313. pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream {
  314. let args = parse_macro_input!(attr as syn::AttributeArgs);
  315. let mut cmd = 0;
  316. let mut flag = true;
  317. let mut manual_flag = false;
  318. for a in args {
  319. match &a {
  320. NestedMeta::Lit(lit) => {
  321. if let syn::Lit::Int(litint) = lit {
  322. cmd = litint.base10_parse().unwrap();
  323. }
  324. },
  325. NestedMeta::Meta(k) => {
  326. if let syn::Meta::Path(syn::Path {segments, ..}) = k {
  327. match segments[0].ident.to_string().as_str() {
  328. "no_flag" => flag = false,
  329. "manual_flag" => {
  330. flag = false;
  331. manual_flag = true;
  332. },
  333. _ => {
  334. return syn::Error::new(segments[0].ident.span(), "unknown macro param").to_compile_error().into();
  335. }
  336. }
  337. }
  338. },
  339. }
  340. }
  341. let pkt_struct = parse_macro_input!(item as ItemStruct);
  342. let attrs = match get_struct_fields(pkt_struct.fields.iter()) {
  343. Ok(a) => a,
  344. Err(err) => return err
  345. };
  346. if manual_flag {
  347. match &attrs[0] {
  348. AttrType::Array(_, ident, _, _) => {
  349. if ident.to_string() != "flag" {
  350. return syn::Error::new(pkt_struct.ident.span(), "struct must have flag as the first field if manual_flag is set").to_compile_error().into();
  351. }
  352. },
  353. AttrType::Value(_, ident, _) => {
  354. if ident.to_string() != "flag" {
  355. return syn::Error::new(pkt_struct.ident.span(), "struct must have flag as the first field if manual_flag is set").to_compile_error().into();
  356. }
  357. }
  358. }
  359. }
  360. let struct_def = generate_struct_def(pkt_struct.ident.clone(), &attrs);
  361. let psopacket_impl = generate_psopacket_impl(cmd, pkt_struct.ident.clone(), &attrs, flag);
  362. let debug_impl = generate_debug_impl(pkt_struct.ident.clone(), &attrs);
  363. let partialeq_impl = generate_partialeq_impl(pkt_struct.ident.clone(), &attrs);
  364. let q = quote!{
  365. #[derive(Clone)]
  366. #struct_def
  367. #psopacket_impl
  368. #debug_impl
  369. #partialeq_impl
  370. };
  371. q.into()
  372. }
  373. fn generate_psomessage_from_bytes(attrs: &Vec<AttrType>) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) {
  374. //let mut from_bytes = Vec::new();
  375. let mut assignment = Vec::new();
  376. let mut structure_creation = Vec::new();
  377. for attr in attrs {
  378. let (assignment_element, creation_element) = match attr {
  379. AttrType::Value(ty, name, meta) => {
  380. let temp_name = syn::Ident::new(&("_".to_string() + &name.to_string()), name.span());
  381. let type_str = ty.path.segments[0].ident.to_string();
  382. if type_str == "Vec" {
  383. let vec_type = match &ty.path.segments[0].arguments {
  384. syn::PathArguments::AngleBracketed(arg) => {
  385. match &arg.args[0] {
  386. syn::GenericArgument::Type(typ) => {
  387. match &typ {
  388. syn::Type::Path(path) => {
  389. Some(path.path.segments[0].ident.clone())
  390. }
  391. _ => None
  392. }
  393. }
  394. _ => None,
  395. }
  396. }
  397. _ => None
  398. }.unwrap();
  399. let length_variable = match meta {
  400. AttrMeta::LengthIs(ident) => syn::Ident::new(&("_".to_string() + &ident.to_string()), ident.span()),
  401. _ => panic!("{} does not have a length specified", name),
  402. };
  403. let assignment = quote! {
  404. let mut #temp_name = Vec::new();
  405. for _ in 0..#length_variable {
  406. #temp_name.push(<#vec_type as PSOPacketData>::from_bytes(&mut cur)?);
  407. }
  408. };
  409. let creation = quote! {
  410. #name: #temp_name,
  411. };
  412. (assignment, creation)
  413. }
  414. else {
  415. let assignment = quote! {
  416. let #temp_name = <#ty as PSOPacketData>::from_bytes(&mut cur)?;
  417. };
  418. let creation = quote! {
  419. #name: #temp_name,
  420. };
  421. (assignment, creation)
  422. }
  423. },
  424. AttrType::Array(ty, name, len, _) => {
  425. let temp_name = syn::Ident::new(&("_".to_string() + &name.to_string()), name.span());
  426. let assignment = quote! {
  427. let #temp_name = {
  428. let mut arr = [#ty::default(); #len];
  429. for e in arr.iter_mut() {
  430. *e = #ty::from_bytes(&mut cur)?
  431. }
  432. arr
  433. };
  434. };
  435. let creation = quote! {
  436. #name: #temp_name,
  437. };
  438. (assignment, creation)
  439. }
  440. };
  441. assignment.push(assignment_element);
  442. structure_creation.push(creation_element);
  443. }
  444. (assignment, structure_creation)
  445. }
  446. fn generate_psomessage_as_bytes(attrs: &Vec<AttrType>) -> Vec<proc_macro2::TokenStream> {
  447. let mut as_bytes = Vec::new();
  448. for attr in attrs {
  449. let element = match attr {
  450. AttrType::Value(ty, name, meta) => {
  451. let type_str = ty.path.segments[0].ident.to_string();
  452. if type_str == "Vec" {
  453. quote! {
  454. for i in self.#name.iter() {
  455. buf.extend_from_slice(&PSOPacketData::as_bytes(i));
  456. }
  457. }
  458. }
  459. else {
  460. if let AttrMeta::LengthOf(ident) = meta {
  461. quote! {
  462. buf.extend_from_slice(&PSOPacketData::as_bytes(&(self.#ident.len() as #ty)));
  463. }
  464. }
  465. else {
  466. quote! {
  467. buf.extend_from_slice(&PSOPacketData::as_bytes(&self.#name));
  468. }
  469. }
  470. }
  471. },
  472. AttrType::Array(_ty, name, len, _) => {
  473. quote! {
  474. for i in 0..#len {
  475. buf.extend_from_slice(&self.#name[i].as_bytes());
  476. }
  477. }
  478. }
  479. };
  480. as_bytes.push(element);
  481. }
  482. as_bytes
  483. }
  484. fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
  485. let (assignment, struct_creation)= generate_psomessage_from_bytes(&attrs);
  486. let as_bytes = generate_psomessage_as_bytes(&attrs);
  487. quote! {
  488. impl PSOMessage for #name {
  489. const CMD: u8 = #msg_cmd;
  490. fn from_bytes<R: std::io::Read + std::io::Seek >(mut cur: &mut R) -> Result<#name, PacketParseError> {
  491. let mut buf1 = [0u8; 1];
  492. cur.read(&mut buf1).unwrap();
  493. let cmd = buf1[0];
  494. cur.read(&mut buf1).unwrap();
  495. let size = buf1[0];
  496. let mut subbuf = vec![0u8; size as usize * 4 - 2];
  497. let len = cur.read(&mut subbuf).unwrap();
  498. if cmd != #msg_cmd {
  499. return Err(PacketParseError::WrongMessageCommand {expected: #msg_cmd, got: cmd});
  500. }
  501. if len != size as usize * 4 - 2 {
  502. return Err(PacketParseError::WrongPacketSize(size as u16 * 4, len));
  503. }
  504. let mut cur = std::io::Cursor::new(subbuf);
  505. #(#assignment)*
  506. let result = Ok(#name {
  507. #(#struct_creation)*
  508. });
  509. result
  510. }
  511. fn as_bytes(&self) -> Vec<u8> {
  512. let mut buf = Vec::new();
  513. #(#as_bytes)*
  514. while buf.len() % 4 != 2 {
  515. buf.push(0);
  516. }
  517. let mut fullbuf = Vec::new();
  518. fullbuf.push(#msg_cmd);
  519. fullbuf.push(((buf.len() + 2) / 4) as u8);
  520. fullbuf.extend_from_slice(&mut buf);
  521. fullbuf
  522. }
  523. }
  524. }
  525. }
  526. #[proc_macro_attribute]
  527. pub fn pso_message(attr: TokenStream, item: TokenStream) -> TokenStream {
  528. let args = parse_macro_input!(attr as syn::AttributeArgs);
  529. let mut cmd = 0;
  530. for a in args {
  531. if let NestedMeta::Lit(lit) = a {
  532. if let syn::Lit::Int(litint) = lit {
  533. cmd = litint.base10_parse().unwrap();
  534. }
  535. }
  536. }
  537. let pkt_struct = parse_macro_input!(item as ItemStruct);
  538. let mut attrs = match get_struct_fields(pkt_struct.fields.iter()) {
  539. Ok(a) => a,
  540. Err(err) => return err
  541. };
  542. // this is a lot of work to make a `u8` token, surely this can be easier?
  543. let mut punctuated: syn::punctuated::Punctuated<syn::PathSegment, syn::Token![::]> = syn::punctuated::Punctuated::new();
  544. punctuated.push_value(syn::PathSegment {
  545. ident: syn::Ident::new("u8", proc_macro2::Span::call_site()),
  546. arguments: syn::PathArguments::None,
  547. });
  548. let u8tpath = syn::TypePath {
  549. qself: None,
  550. path: syn::Path {
  551. leading_colon: None,
  552. segments: punctuated
  553. }
  554. };
  555. attrs.insert(0, AttrType::Value(u8tpath.clone(), syn::Ident::new("target", proc_macro2::Span::call_site()), AttrMeta::None));
  556. attrs.insert(0, AttrType::Value(u8tpath, syn::Ident::new("client", proc_macro2::Span::call_site()), AttrMeta::None));
  557. let struct_def = generate_struct_def(pkt_struct.ident.clone(), &attrs);
  558. let psopacket_impl = generate_psomessage_impl(cmd, pkt_struct.ident.clone(), &attrs);
  559. let debug_impl = generate_debug_impl(pkt_struct.ident.clone(), &attrs);
  560. let partialeq_impl = generate_partialeq_impl(pkt_struct.ident.clone(), &attrs);
  561. let q = quote!{
  562. #[derive(Clone)]
  563. #struct_def
  564. #psopacket_impl
  565. #debug_impl
  566. #partialeq_impl
  567. };
  568. q.into()
  569. }
  570. #[proc_macro_derive(PSOPacketData)]
  571. pub fn pso_packet_data(input: TokenStream) -> TokenStream {
  572. let derive = parse_macro_input!(input as DeriveInput);
  573. let name = derive.ident;
  574. let fields = if let syn::Data::Struct(strct) = derive.data {
  575. strct.fields
  576. }
  577. else {
  578. return syn::Error::new(name.span(), "PSOPacketData only works on structs").to_compile_error().into();
  579. };
  580. let attrs = match get_struct_fields(fields.iter()) {
  581. Ok(a) => a,
  582. Err(err) => return err
  583. };
  584. let from_bytes = generate_from_bytes(&attrs);
  585. let as_bytes = generate_as_bytes(&attrs);
  586. let impl_pso_data_packet = quote! {
  587. impl PSOPacketData for #name {
  588. fn from_bytes<R: std::io::Read + std::io::Seek>(mut cur: &mut R) -> Result<Self, PacketParseError> {
  589. Ok(#name {
  590. #(#from_bytes)*
  591. })
  592. }
  593. fn as_bytes(&self) -> Vec<u8> {
  594. let mut buf = Vec::new();
  595. #(#as_bytes)*
  596. buf
  597. }
  598. }
  599. };
  600. let partialeq = generate_partialeq_impl(name.clone(), &attrs);
  601. let debug = generate_debug_impl(name, &attrs);
  602. let q = quote! {
  603. #impl_pso_data_packet
  604. #partialeq
  605. #debug
  606. };
  607. q.into()
  608. }