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.

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