1 use std::io::{self, Write};
2
3 use super::ffi;
4
5 use super::{
6 emit_doc_field, emit_doc_field_indent, emit_doc_text, enum_suffix_exception, expr_fixed_length,
7 extract_module, field_name, qualified_name, request_has_template, tit_cap, tit_dig_split,
8 CodeGen, ListField, KEYWORDS,
9 };
10 use crate::ast::{Doc, OpCopy, Reply, Struct, StructField, SwitchCase};
11
12 impl CodeGen {
has_rs_type(&self, typ: &str) -> bool13 fn has_rs_type(&self, typ: &str) -> bool {
14 self.rs_typ_reg.contains(typ)
15 }
16
rs_enum_type_name(&mut self, typ: &str) -> String17 pub fn rs_enum_type_name(&mut self, typ: &str) -> String {
18 let try1 = type_name(typ);
19 if self.has_rs_type(&try1) || enum_suffix_exception(&self.xcb_mod, typ) {
20 format!("{}Enum", &try1)
21 } else {
22 try1
23 }
24 }
25
rs_use_type_name(&self, typ: &str) -> String26 fn rs_use_type_name(&self, typ: &str) -> String {
27 let (module, typ) = extract_module(typ);
28
29 let module = module.or_else(|| {
30 if self.has_type(typ) {
31 None
32 } else {
33 let mut module = None;
34 for di in self.dep_info.iter() {
35 if di.has_type(typ) {
36 module = Some(di.xcb_mod.as_str());
37 break;
38 }
39 }
40 module
41 }
42 });
43
44 let typ = type_name(typ);
45
46 qualified_name(&self.xcb_mod, &module, &typ)
47 }
48
emit_rs_struct_field_accessors( &mut self, typ_name: &str, stru: &Struct, accessor: &str, skip_fields: &[&str], has_lifetime: bool, is_reply: bool, ) -> io::Result<()>49 fn emit_rs_struct_field_accessors(
50 &mut self,
51 typ_name: &str,
52 stru: &Struct,
53 accessor: &str,
54 skip_fields: &[&str],
55 has_lifetime: bool,
56 is_reply: bool,
57 ) -> io::Result<()> {
58 let has_reply_fd_nfd = is_reply && has_fd_nfd(&stru.fields);
59 for f in stru.fields.iter() {
60 match f {
61 StructField::Field { name, typ, .. } => {
62 if skip_fields.iter().any(|skip| skip == name) {
63 continue;
64 }
65 if has_reply_fd_nfd && name == "nfd" {
66 continue;
67 }
68 let is_simple = self.typ_is_simple(typ);
69 let is_pod = self.typ_is_pod(typ);
70
71 let rs_typ = self.rs_use_type_name(typ);
72
73 let out = &mut self.rs_buf;
74 emit_doc_field(out, &stru.doc, name)?;
75
76 let f_name = field_name(name);
77
78 if !self.typ_unions.contains(typ) {
79 writeln!(out, " pub fn {}(&self) -> {} {{", &f_name, rs_typ,)?;
80 if typ == "BOOL" {
81 writeln!(out, " unsafe {{ {}.{} != 0 }}", &accessor, &f_name)?;
82 } else if is_pod && !is_simple {
83 writeln!(
84 out,
85 " unsafe {{ std::mem::transmute({}.{}) }}",
86 &accessor, &f_name
87 )?;
88 } else if !is_pod && !is_simple {
89 writeln!(
90 out,
91 " unsafe {{ std::mem::transmute(&{}.{}) }}",
92 &accessor, &f_name
93 )?;
94 } else {
95 writeln!(out, " unsafe {{ {}.{} }}", &accessor, &f_name)?;
96 }
97 } else {
98 // unions are returned by ref and need lifetime (TODO: check if really needed)
99 // adding lifetime declaration if not already declared in the impl opening
100 let lifetime_decl = if has_lifetime { "" } else { "<'a>" };
101 writeln!(
102 out,
103 " pub fn {}{}(&'a self) -> &'a {} {{",
104 &name, &lifetime_decl, &rs_typ
105 )?;
106 writeln!(out, " unsafe {{ &{}.{} }}", &accessor, &name)?;
107 }
108 writeln!(out, " }}")?;
109 }
110 StructField::List {
111 name,
112 typ,
113 len_expr,
114 } => {
115 if skip_fields.iter().any(|skip| skip == name) {
116 continue;
117 }
118 let f_name = field_name(name);
119 let is_simple = self.typ_is_simple(typ);
120 let is_string = typ == "char";
121 let fixed_len = expr_fixed_length(len_expr);
122
123 let rs_typ = self.rs_use_type_name(typ);
124
125 if fixed_len.is_some() {
126 let out = &mut self.rs_buf;
127 writeln!(out, " pub fn {}(&self) -> &[{}] {{", &f_name, &rs_typ)?;
128 writeln!(out, " unsafe {{ &(*self.ptr).{} }}", &f_name)?;
129 writeln!(out, " }}")?;
130 } else if is_simple {
131 let len_fn = ffi::field_list_iterator_len_fn_name(
132 &self.xcb_mod_prefix,
133 &stru.name,
134 name,
135 );
136 let acc_fn = ffi::field_list_iterator_acc_fn_name(
137 &self.xcb_mod_prefix,
138 &stru.name,
139 name,
140 );
141 let is_template = typ == "void";
142 let template = if is_template { "<T>" } else { "" };
143 let ret = match typ.as_str() {
144 "char" => "&str".to_string(),
145 "void" => "&[T]".to_string(),
146 "BOOL" => "Vec<bool>".to_string(),
147 _ => format!("&[{}]", &rs_typ),
148 };
149 let out = &mut self.rs_buf;
150 writeln!(
151 out,
152 " pub fn {}{}(&self) -> {} {{",
153 &f_name, &template, &ret
154 )?;
155 writeln!(out, " unsafe {{")?;
156 writeln!(out, " let field = self.ptr;")?;
157 writeln!(out, " let len = {}(field) as usize;", &len_fn)?;
158 writeln!(out, " let data = {}(field);", &acc_fn)?;
159 if typ == "BOOL" {
160 writeln!(
161 out,
162 " let slice = std::slice::from_raw_parts(data, len);"
163 )?;
164 writeln!(out, " slice.iter().map(|el| if *el == 0 {{ false }} else {{ true }}).collect()")?;
165 } else if is_string {
166 writeln!(out, " let slice = std::slice::from_raw_parts(data as *const u8, len);")?;
167 writeln!(out, " // should we check what comes from X?")?;
168 writeln!(out, " std::str::from_utf8_unchecked(&slice)")?;
169 } else if is_template {
170 writeln!(
171 out,
172 " debug_assert_eq!(len % std::mem::size_of::<T>(), 0);"
173 )?;
174 writeln!(out, " std::slice::from_raw_parts(data as *const T, len / std::mem::size_of::<T>())")?;
175 } else {
176 writeln!(out, " std::slice::from_raw_parts(data, len)")?;
177 }
178 writeln!(out, " }}")?;
179 writeln!(out, " }}")?;
180 } else {
181 let has_lifetime = has_lifetime && self.typ_with_lifetime.contains(typ);
182 let lifetime = if has_lifetime { "<'a>" } else { "" };
183 let it_typ = self.rs_use_type_name(typ) + "Iterator";
184 let ffi_it_fn_name = ffi::field_list_iterator_it_fn_name(
185 &self.xcb_mod_prefix,
186 typ_name,
187 name,
188 );
189 let out = &mut self.rs_buf;
190 writeln!(
191 out,
192 " pub fn {}(&self) -> {}{} {{",
193 &f_name, &it_typ, &lifetime
194 )?;
195 writeln!(out, " unsafe {{ {}(self.ptr) }}", &ffi_it_fn_name)?;
196 writeln!(out, " }}")?;
197 }
198 }
199 StructField::ListNoLen { name, typ } => {
200 let has_lifetime = has_lifetime && self.typ_with_lifetime.contains(typ);
201 let lifetime = if has_lifetime { "<'a>" } else { "" };
202 // let len_name = name.clone() + "_len";
203 let rs_name = field_name(name);
204 let it_typ = self.rs_use_type_name(typ) + "Iterator";
205 let ffi_it_fn_name =
206 ffi::field_list_iterator_it_fn_name(&self.xcb_mod_prefix, typ_name, name);
207 let out = &mut self.rs_buf;
208 // writeln!(out, " pub fn {}(&self) -> u32 {{", &len_name)?;
209 // writeln!(out, " unsafe {{ {}.{} }}", &accessor, &len_name)?;
210 // writeln!(out, " }}")?;
211 writeln!(
212 out,
213 " pub fn {}(&self) -> {}{} {{",
214 &rs_name, &it_typ, &lifetime
215 )?;
216 writeln!(out, " unsafe {{ {}(self.ptr) }}", &ffi_it_fn_name)?;
217 writeln!(out, " }}")?;
218 }
219 StructField::ValueParam {
220 mask_typ,
221 mask_name,
222 list_name,
223 } => {
224 let rs_mask_typ = type_name(mask_typ);
225 let f_mask_name = field_name(mask_name);
226 let rs_list_name = field_name(list_name);
227 let len_fn = ffi::field_list_iterator_len_fn_name(
228 &self.xcb_mod_prefix,
229 &stru.name,
230 list_name,
231 );
232 let acc_fn = ffi::field_list_iterator_acc_fn_name(
233 &self.xcb_mod_prefix,
234 &stru.name,
235 list_name,
236 );
237 let out = &mut self.rs_buf;
238 writeln!(
239 out,
240 " pub fn {}(&self) -> {} {{",
241 &f_mask_name, &rs_mask_typ
242 )?;
243 writeln!(out, " unsafe {{ (*self.ptr).{} }}", &f_mask_name)?;
244 writeln!(out, " }}")?;
245 writeln!(out, " pub fn {}(&self) -> &[u32] {{", &rs_list_name)?;
246 writeln!(out, " unsafe {{")?;
247 writeln!(out, " let field = self.ptr;")?;
248 writeln!(out, " let len = {}(field) as usize;", len_fn)?;
249 writeln!(out, " let data = {}(field);", acc_fn)?;
250 writeln!(out, " std::slice::from_raw_parts(data, len)")?;
251 writeln!(out, " }}")?;
252 writeln!(out, " }}")?;
253 }
254 _ => {}
255 }
256 }
257
258 if has_reply_fd_nfd {
259 for f in stru.fields.iter() {
260 if let StructField::Fd(name) = f {
261 let getter = ffi::reply_fds_fn_name(&self.xcb_mod_prefix, &stru.name);
262 let out = &mut self.rs_buf;
263 writeln!(
264 out,
265 " pub fn {}s(&self, c: &base::Connection) -> &[i32] {{",
266 name
267 )?;
268 writeln!(out, " unsafe {{")?;
269 writeln!(out, " let nfd = {}.nfd as usize;", &accessor)?;
270 writeln!(
271 out,
272 " let ptr = {}(c.get_raw_conn(), self.ptr);",
273 &getter
274 )?;
275 writeln!(out, " std::slice::from_raw_parts(ptr, nfd)")?;
276 writeln!(out, " }}")?;
277 writeln!(out, " }}")?;
278 }
279 }
280 }
281
282 Ok(())
283 }
284
emit_rs_struct_impl( &mut self, rs_typ: &str, ffi_typ: &str, stru: &Struct, has_lifetime: bool, is_pod: bool, ) -> io::Result<()>285 fn emit_rs_struct_impl(
286 &mut self,
287 rs_typ: &str,
288 ffi_typ: &str,
289 stru: &Struct,
290 has_lifetime: bool,
291 is_pod: bool,
292 ) -> io::Result<()> {
293 let (accessor, lifetime) = if has_lifetime {
294 ("(*self.ptr)", "<'a>")
295 } else {
296 ("self.base", "")
297 };
298 // emitting struct impl
299 {
300 let out = &mut self.rs_buf;
301
302 writeln!(out)?;
303 writeln!(out, "impl{} {}{} {{", &lifetime, &rs_typ, &lifetime)?;
304 }
305
306 // emitting ctor
307 if is_pod {
308 {
309 let out = &mut self.rs_buf;
310 writeln!(out, " #[allow(unused_unsafe)]")?;
311 write!(out, " pub fn new(")?;
312 }
313 for f in stru.fields.iter() {
314 if let StructField::Field { name, typ, .. } = f {
315 let rs_typ = self.rs_use_type_name(typ);
316 let name = field_name(name);
317 write!(&mut self.rs_buf, "{}: {},", name, rs_typ)?;
318 }
319 }
320 {
321 let out = &mut self.rs_buf;
322 writeln!(out, ") -> {} {{", &rs_typ)?;
323 writeln!(out, " unsafe {{")?;
324 writeln!(out, " {} {{", &rs_typ)?;
325 writeln!(out, " base: {} {{", &ffi_typ)?;
326 }
327 for f in stru.fields.iter() {
328 match f {
329 StructField::Field { name, typ, .. } => {
330 let f_name = field_name(name);
331 let name = field_name(name);
332 let is_pod = self.typ_is_pod(typ);
333 let is_simple = self.typ_is_simple(typ);
334 let out = &mut self.rs_buf;
335 if typ == "BOOL" {
336 writeln!(
337 out,
338 " {}: if {} {{ 1 }} else {{ 0 }},",
339 &f_name, &name
340 )?;
341 } else if is_pod && !is_simple {
342 writeln!(
343 out,
344 " {}: std::mem::transmute({}),",
345 &f_name, &name
346 )?;
347 } else {
348 writeln!(out, " {}: {},", &f_name, &name)?;
349 }
350 }
351 StructField::Pad(name, sz) => {
352 let val = if *sz == 1 {
353 "0".into()
354 } else {
355 format!("[0; {}]", sz)
356 };
357 let out = &mut self.rs_buf;
358 writeln!(out, " {}: {},", name, val)?;
359 }
360 _ => {}
361 }
362 }
363 let out = &mut self.rs_buf;
364 writeln!(out, " }}")?;
365 writeln!(out, " }}")?;
366 writeln!(out, " }}")?;
367 writeln!(out, " }}")?;
368 }
369
370 // emitting accessors
371 self.emit_rs_struct_field_accessors(&stru.name, stru, accessor, &[], has_lifetime, false)?;
372
373 writeln!(&mut self.rs_buf, "}}")?;
374
375 Ok(())
376 }
377
emit_rs_iterator( &mut self, name: &str, typ: &str, ffi_it_typ: &str, has_lifetime: bool, is_union: bool, ) -> io::Result<()>378 pub fn emit_rs_iterator(
379 &mut self,
380 name: &str,
381 typ: &str,
382 ffi_it_typ: &str,
383 has_lifetime: bool,
384 is_union: bool,
385 ) -> io::Result<()> {
386 let it_typ = format!("{}Iterator", &typ);
387 let ffi_it_next = ffi::iterator_next_fn_name(&self.xcb_mod_prefix, name);
388
389 let lifetime = if has_lifetime { "<'a>" } else { "" };
390
391 let return_expr = match (has_lifetime, is_union) {
392 (true, true) => unimplemented!(),
393 (true, false) => "std::mem::transmute(data)",
394 (false, true) => "*data",
395 (false, false) => "std::mem::transmute(*data)",
396 };
397
398 let out = &mut self.rs_buf;
399
400 writeln!(out)?;
401 writeln!(
402 out,
403 "pub type {}{} = {}{};",
404 &it_typ, &lifetime, &ffi_it_typ, &lifetime
405 )?;
406 writeln!(out)?;
407 writeln!(
408 out,
409 "impl{} Iterator for {}{} {{",
410 &lifetime, &it_typ, &lifetime
411 )?;
412 writeln!(out, " type Item = {}{};", &typ, &lifetime)?;
413 writeln!(
414 out,
415 " fn next(&mut self) -> std::option::Option<{}{}> {{",
416 &typ, &lifetime,
417 )?;
418 writeln!(out, " if self.rem == 0 {{")?;
419 writeln!(out, " None")?;
420 writeln!(out, " }} else {{")?;
421 writeln!(out, " unsafe {{")?;
422 writeln!(
423 out,
424 " let iter = self as *mut {};",
425 &ffi_it_typ
426 )?;
427 writeln!(out, " let data = (*iter).data;")?;
428 writeln!(out, " {}(iter);", &ffi_it_next)?;
429 writeln!(out, " Some({})", &return_expr)?;
430 writeln!(out, " }}")?;
431 writeln!(out, " }}")?;
432 writeln!(out, " }}")?;
433 writeln!(out, "}}")?;
434
435 Ok(())
436 }
437
emit_rs_struct( &mut self, ffi_typ: &str, stru: &Struct, has_lifetime: bool, ) -> io::Result<String>438 pub fn emit_rs_struct(
439 &mut self,
440 ffi_typ: &str,
441 stru: &Struct,
442 has_lifetime: bool,
443 ) -> io::Result<String> {
444 let Struct { name, doc, .. } = &stru;
445
446 let typ = type_name(name);
447
448 let out = &mut self.rs_buf;
449 // emitting struct
450 writeln!(out)?;
451 emit_doc_text(out, doc)?;
452 if has_lifetime {
453 writeln!(
454 out,
455 "pub type {}<'a> = base::StructPtr<'a, {}>;",
456 &typ, &ffi_typ
457 )?;
458 } else {
459 writeln!(out, "#[derive(Copy, Clone)]")?;
460 writeln!(out, "pub struct {} {{", &typ)?;
461 writeln!(out, " pub base: {},", &ffi_typ)?;
462 writeln!(out, "}}")?;
463 }
464
465 self.emit_rs_struct_impl(&typ, ffi_typ, stru, has_lifetime, !has_lifetime)?;
466
467 Ok(typ)
468 }
469
emit_rs_union_impl( &mut self, rs_typ: &str, ffi_sz: usize, stru: &Struct, ) -> io::Result<()>470 pub fn emit_rs_union_impl(
471 &mut self,
472 rs_typ: &str,
473 ffi_sz: usize,
474 stru: &Struct,
475 ) -> io::Result<()> {
476 let Struct { fields, doc, .. } = &stru;
477
478 {
479 let out = &mut self.rs_buf;
480 writeln!(out)?;
481 writeln!(out, "impl {} {{", &rs_typ)?;
482 }
483
484 // emitting accessors
485 for f in fields.iter() {
486 match f {
487 StructField::Field { name, typ, .. } => {
488 let rs_name = field_name(name);
489 let f_rs_typ = self.rs_use_type_name(typ);
490 let has_lifetime = self.type_has_lifetime(typ);
491
492 let out = &mut self.rs_buf;
493 emit_doc_field(out, doc, name)?;
494
495 if has_lifetime {
496 writeln!(
497 out,
498 " pub fn {}<'a> (&'a self) -> {}<'a> {{",
499 &rs_name, &f_rs_typ
500 )?;
501 writeln!(out, " unsafe {{ std::mem::transmute(self) }}")?;
502 } else {
503 writeln!(out)?;
504 writeln!(out, " pub fn {}(&self) -> {} {{", &rs_name, &f_rs_typ)?;
505 writeln!(out, " unsafe {{")?;
506 writeln!(
507 out,
508 " let _ptr = self.data.as_ptr() as *const {};",
509 &f_rs_typ
510 )?;
511 writeln!(out, " *_ptr")?;
512 writeln!(out, " }}")?;
513 writeln!(out, " }}")?;
514 writeln!(
515 out,
516 " pub fn from_{}({}: {}) -> {} {{",
517 &rs_name, &rs_name, &f_rs_typ, &rs_typ
518 )?;
519 writeln!(out, " unsafe {{")?;
520 writeln!(
521 out,
522 " let mut res = {} {{ data: [0; {}] }};",
523 &rs_typ, ffi_sz
524 )?;
525 writeln!(
526 out,
527 " let res_ptr = res.data.as_mut_ptr() as *mut {};",
528 &f_rs_typ
529 )?;
530 writeln!(out, " *res_ptr = {};", &rs_name)?;
531 writeln!(out, " res")?;
532 writeln!(out, " }}")?;
533 }
534 writeln!(out, " }}")?;
535 }
536 StructField::List {
537 name,
538 typ,
539 len_expr,
540 } => {
541 let rs_name = field_name(name);
542 let f_rs_typ = self.rs_use_type_name(typ);
543 let len =
544 expr_fixed_length(len_expr).expect("union list field with variable length");
545
546 let out = &mut self.rs_buf;
547 emit_doc_field(out, doc, name)?;
548 // accessor
549 writeln!(out, " pub fn {}(&self) -> &[{}] {{", &rs_name, &f_rs_typ)?;
550 writeln!(out, " unsafe {{")?;
551 writeln!(
552 out,
553 " let ptr = self.data.as_ptr() as *const {};",
554 &f_rs_typ
555 )?;
556 writeln!(out, " std::slice::from_raw_parts(ptr, {})", len)?;
557 writeln!(out, " }}")?;
558 writeln!(out, " }}")?;
559 // constructor
560 writeln!(
561 out,
562 " pub fn from_{}({}: [{}; {}]) -> {} {{",
563 &rs_name, &rs_name, &f_rs_typ, len, &rs_typ
564 )?;
565 writeln!(out, " unsafe {{")?;
566 writeln!(out, " {} {{", &rs_typ)?;
567 writeln!(
568 out,
569 " data: std::mem::transmute({})",
570 &rs_name
571 )?;
572 writeln!(out, " }}")?;
573 writeln!(out, " }}")?;
574 writeln!(out, " }}")?;
575 }
576 _ => {
577 unimplemented!();
578 }
579 }
580 }
581 let out = &mut self.rs_buf;
582 writeln!(out, "}}")?;
583
584 Ok(())
585 }
586
emit_rs_event( &mut self, name: &str, number: i32, stru: &Struct, ffi_typ: &str, opcopies: &[OpCopy], xge: bool, ) -> io::Result<String>587 pub fn emit_rs_event(
588 &mut self,
589 name: &str,
590 number: i32,
591 stru: &Struct,
592 ffi_typ: &str,
593 opcopies: &[OpCopy],
594 xge: bool,
595 ) -> io::Result<String> {
596 let rs_typ = type_name(&stru.name);
597
598 let opn = opname(name);
599 let num_typ = if number < 0 { "i8" } else { "u8" };
600
601 {
602 let out = &mut self.rs_buf;
603 writeln!(out)?;
604 writeln!(out, "pub const {}: {} = {};", &opn, &num_typ, number)?;
605
606 writeln!(out)?;
607 emit_doc_text(out, &stru.doc)?;
608 writeln!(out, "pub type {} = base::Event<{}>;", &rs_typ, &ffi_typ)?;
609
610 writeln!(out)?;
611 writeln!(out, "impl {} {{", &rs_typ)?;
612 }
613
614 let field_skip = {
615 let mut fs = if xge {
616 vec![
617 "sequence",
618 "extension",
619 "length",
620 "event_type",
621 "full_sequence",
622 ]
623 } else {
624 vec!["sequence"]
625 };
626 if opcopies.is_empty() {
627 fs.push("response_type");
628 }
629 fs
630 };
631
632 {
633 let mut fs = field_skip.clone();
634 fs.push("response_type");
635 self.emit_rs_struct_field_accessors(name, stru, "(*self.ptr)", &fs, false, false)?;
636 }
637
638 // emitting ctor
639 if !has_variable_list(&stru.fields) {
640 {
641 let out = &mut self.rs_buf;
642
643 writeln!(out, " /// Constructs a new {}", &rs_typ)?;
644 if opcopies.is_empty() {
645 writeln!(
646 out,
647 " /// `response_type` will be set automatically to {}",
648 &opn
649 )?;
650 } else {
651 writeln!(out, " /// `response_type` must be set to one of:")?;
652 writeln!(out, " /// - `{}`", &opn)?;
653 for op in opcopies.iter() {
654 let opn = opname(&op.name);
655 writeln!(out, " /// - `{}`", &opn)?;
656 }
657 }
658
659 writeln!(out, " pub fn new (")?;
660 }
661
662 for f in stru.fields.iter() {
663 match f {
664 StructField::Field { name, typ, .. } => {
665 if field_skip.iter().any(|skip| skip == name) {
666 continue;
667 }
668 let rs_typ = self.rs_use_type_name(typ);
669 writeln!(
670 &mut self.rs_buf,
671 " {}: {},",
672 field_name(name),
673 &rs_typ
674 )?;
675 }
676 StructField::Pad(_, _) => {}
677 StructField::List {
678 name,
679 typ,
680 len_expr,
681 } => {
682 if field_skip.iter().any(|skip| skip == name) {
683 continue;
684 }
685 let typ = match typ.as_str() {
686 "char" => "&str".into(),
687 typ => {
688 let typ = self.rs_use_type_name(typ);
689 if let Some(len) = expr_fixed_length(len_expr) {
690 format!("[{}; {}]", &typ, len)
691 } else {
692 format!("&[{}]", &typ)
693 }
694 }
695 };
696 writeln!(&mut self.rs_buf, " {}: {},", field_name(name), &typ)?;
697 }
698 StructField::ListNoLen { name, typ } => {
699 let len_name = name.clone() + "_len";
700 let typ = self.rs_use_type_name(typ);
701 writeln!(&mut self.rs_buf, " {}: u32,", len_name)?;
702 writeln!(&mut self.rs_buf, " {}: {},", field_name(name), typ)?;
703 }
704 _ => unimplemented!("{}::{}::{:?}", self.xcb_mod, &rs_typ, f),
705 }
706 }
707
708 {
709 let out = &mut self.rs_buf;
710
711 writeln!(out, " ) -> {} {{", &rs_typ)?;
712 writeln!(out, " unsafe {{")?;
713 writeln!(
714 out,
715 " let raw = libc::malloc(32 as usize) as *mut {};",
716 &ffi_typ
717 )?;
718 if !opcopies.is_empty() {
719 let copies = opcopies.iter().map(|opc| opname(&opc.name));
720 let opcodes = Some(opn.clone()).into_iter().chain(copies);
721 let assert_expr = opcodes
722 .map(|opc| format!("response_type == {}", &opc))
723 .collect::<Vec<String>>()
724 .join(" || ");
725 writeln!(
726 out,
727 " assert!({}, \"wrong response_type supplied to {}::new\");",
728 &assert_expr, &rs_typ
729 )?;
730 } else {
731 writeln!(out, " (*raw).response_type = {};", &opn)?;
732 }
733 }
734
735 for f in stru.fields.iter() {
736 match f {
737 StructField::Field { name, typ, .. } => {
738 if field_skip.iter().any(|skip| skip == name) {
739 continue;
740 }
741 let f_name = field_name(name);
742 let is_simple = self.typ_is_simple(typ);
743 let is_pod = self.typ_is_pod(typ);
744
745 let expr = if !is_simple && is_pod {
746 format!("{}.base", &f_name)
747 } else if typ == "BOOL" {
748 format!("if {} {{ 1 }} else {{ 0 }}", f_name)
749 } else {
750 f_name.clone()
751 };
752
753 writeln!(
754 &mut self.rs_buf,
755 " (*raw).{} = {};",
756 f_name, expr
757 )?;
758 }
759 StructField::List { name, .. } => {
760 let f_name = field_name(name);
761 writeln!(
762 &mut self.rs_buf,
763 " (*raw).{} = {};",
764 f_name, f_name
765 )?;
766 }
767 StructField::ListNoLen { name, .. } => {
768 let len_name = name.clone() + "_len";
769 let f_name = field_name(name);
770 writeln!(
771 &mut self.rs_buf,
772 " (*raw).{} = {};",
773 len_name, len_name
774 )?;
775 writeln!(
776 &mut self.rs_buf,
777 " (*raw).{} = {};",
778 f_name, f_name
779 )?;
780 }
781 _ => {}
782 }
783 }
784
785 let out = &mut self.rs_buf;
786
787 writeln!(out, " {} {{ ptr: raw }}", &rs_typ)?;
788 writeln!(out, " }}")?; // closing unsafe
789 writeln!(out, " }}")?; // closing new
790 }
791
792 writeln!(&mut self.rs_buf, "}}")?; // closing impl
793
794 for opc in opcopies.iter() {
795 let opn = opname(&opc.name);
796 let name = opc.name.clone() + "Event";
797 let num_typ = if number < 0 { "i8" } else { "u8" };
798 let rs_typ = type_name(&name);
799 let ffi_typ = self.ffi_decl_type_name(&name);
800
801 let out = &mut self.rs_buf;
802 writeln!(out)?;
803 writeln!(out, "pub const {}: {} = {};", &opn, &num_typ, &opc.number)?;
804
805 writeln!(out)?;
806 emit_doc_text(out, &stru.doc)?;
807 writeln!(out, "pub type {} = base::Event<{}>;", &rs_typ, &ffi_typ)?;
808 }
809
810 Ok(rs_typ)
811 }
812
emit_rs_switch_typedef( &mut self, req_name: &str, switch_name: &str, cases: &[SwitchCase], toplevel_typ: &str, _parent_switch: Option<&str>, ) -> io::Result<()>813 pub fn emit_rs_switch_typedef(
814 &mut self,
815 req_name: &str,
816 switch_name: &str,
817 cases: &[SwitchCase],
818 toplevel_typ: &str,
819 _parent_switch: Option<&str>,
820 ) -> io::Result<()> {
821 let ffi_typ = ffi::switch_struct_name(&self.xcb_mod_prefix, req_name, switch_name);
822 let rs_typ = switch_type_name(req_name, switch_name);
823
824 let out = &mut self.rs_buf;
825
826 writeln!(
827 out,
828 "pub type {}<'a> = base::StructPtr<'a, {}>;",
829 &rs_typ, &ffi_typ
830 )?;
831
832 for c in cases.iter() {
833 for f in c.fields.iter() {
834 if let StructField::Switch(cname, _, ccases) = f {
835 let rs_typ = if let Some(name) = &c.name {
836 rs_typ.clone() + &tit_cap(name)
837 } else {
838 rs_typ.clone()
839 };
840 self.emit_rs_switch_typedef(
841 &rs_typ,
842 cname,
843 ccases,
844 toplevel_typ,
845 Some(&ffi_typ),
846 )?;
847 }
848 }
849 }
850
851 Ok(())
852 }
853
854 #[allow(clippy::too_many_arguments)]
emit_rs_req_fn( &mut self, req_name: &str, fn_name: &str, ffi_fn_name: &str, cookie_name: &str, params: &[StructField], doc: &Option<Doc>, checked: bool, ) -> io::Result<()>855 pub fn emit_rs_req_fn(
856 &mut self,
857 req_name: &str,
858 fn_name: &str,
859 ffi_fn_name: &str,
860 cookie_name: &str,
861 params: &[StructField],
862 doc: &Option<Doc>,
863 checked: bool,
864 ) -> io::Result<()> {
865 // special case for the send_event request
866 let send_event = match (req_name, self.xcb_mod.as_str()) {
867 ("SendEvent", "xproto") => true,
868 ("Send", "xevie") => true,
869 (_, _) => false,
870 };
871 let event_is_list = if send_event {
872 let mut is_list = false;
873 for f in params.iter() {
874 if let StructField::List { name, .. } = f {
875 if name == "event" {
876 is_list = true;
877 break;
878 }
879 }
880 }
881 is_list
882 } else {
883 false
884 };
885
886 let has_template = request_has_template(params) || event_is_list;
887 let list_fields = ListField::fetch_from(params);
888 let skip_fields = {
889 let mut sf = Vec::new();
890
891 for f in params.iter() {
892 if let StructField::ValueParam { mask_name, .. } = f {
893 sf.push(mask_name.clone());
894 }
895 }
896
897 sf
898 };
899
900 let template = if has_template { ", T" } else { "" };
901
902 {
903 let out = &mut self.rs_buf;
904
905 writeln!(out)?;
906 emit_doc_text(out, doc)?;
907 if doc.is_some() {
908 writeln!(out, "///")?;
909 writeln!(out, "/// parameters:")?;
910 writeln!(out, "///")?;
911 writeln!(out, "/// - __c__:")?;
912 writeln!(out, "/// The connection object to the server")?;
913 for f in params.iter() {
914 if let Some(name) = field_doc_name(f) {
915 writeln!(out, "///")?;
916 writeln!(out, "/// - __{}__:", &name)?;
917 emit_doc_field_indent(out, doc, &name, " ")?;
918 }
919 }
920 }
921 writeln!(out, "pub fn {}<'a{}>(", &fn_name, &template)?;
922
923 writeln!(out, " c: &'a base::Connection,")?;
924 }
925
926 // request parameters
927 for f in params.iter() {
928 match f {
929 StructField::Field { name, typ, .. } => {
930 if skip_fields.contains(name) {
931 continue;
932 }
933 if list_fields.iter().any(|lf| &lf.lenfield == name) {
934 continue;
935 }
936 let name = field_name(name);
937 let typ = self.rs_use_type_name(typ);
938 let out = &mut self.rs_buf;
939 writeln!(out, " {}: {},", name, typ)?;
940 }
941 StructField::Fd(name) => {
942 let name = field_name(name);
943 writeln!(&mut self.rs_buf, " {}: i32,", name)?;
944 }
945 StructField::List { name, typ, .. } | StructField::ListNoLen { name, typ } => {
946 let name = field_name(name);
947 let typ = match (send_event, name.as_str(), typ.as_str()) {
948 (true, "event", _) => "&base::Event<T>".to_string(),
949 (_, _, "char") => "&str".to_string(),
950 (_, _, "void") => "&[T]".to_string(),
951 (_, _, typ) => {
952 format!("&[{}]", self.rs_use_type_name(typ))
953 }
954 };
955 let out = &mut self.rs_buf;
956 writeln!(out, " {}: {},", name, typ)?;
957 }
958 StructField::ValueParam {
959 list_name,
960 mask_typ,
961 ..
962 } => {
963 let name = field_name(list_name);
964 let typ = self.rs_use_type_name(mask_typ);
965 let out = &mut self.rs_buf;
966 writeln!(out, " {}: &[({}, u32)],", &name, &typ)?;
967 }
968 StructField::Switch(name, ..) => {
969 let rs_typ = switch_type_name(req_name, name);
970 let name = field_name(name);
971 let out = &mut self.rs_buf;
972 writeln!(out, " {}: std::option::Option<{}>,", &name, &rs_typ)?;
973 }
974 _ => {}
975 }
976 }
977
978 let out = &mut self.rs_buf;
979 writeln!(out, ") -> {}<'a> {{", cookie_name)?;
980 writeln!(out, " unsafe {{")?;
981
982 let mut issued_len_vars = Vec::new();
983 let mut issued_list_vars = Vec::new();
984
985 // local variables
986 if event_is_list {
987 writeln!(
988 out,
989 " let event_ptr = std::mem::transmute(event.ptr);"
990 )?;
991 }
992 for ListField {
993 name,
994 typ,
995 lenfield,
996 } in list_fields.iter()
997 {
998 issued_list_vars.push(name);
999 let name = field_name(name);
1000 if typ == "char" {
1001 writeln!(out, " let {} = {}.as_bytes();", &name, &name)?;
1002 }
1003 if !issued_len_vars.contains(&lenfield) {
1004 writeln!(out, " let {}_len = {}.len();", &name, &name)?;
1005 issued_len_vars.push(lenfield);
1006 }
1007 writeln!(out, " let {}_ptr = {}.as_ptr();", &name, &name)?;
1008 }
1009 for f in params.iter() {
1010 match f {
1011 StructField::List { name, .. } => {
1012 if issued_list_vars.contains(&name) {
1013 continue;
1014 }
1015 if send_event && name == "event" {
1016 continue;
1017 }
1018 let name = field_name(name);
1019 writeln!(out, " let {}_ptr = {}.as_ptr();", &name, &name)?;
1020 }
1021 StructField::ValueParam { list_name, .. } => {
1022 let list_sym = field_name(list_name);
1023 writeln!(
1024 out,
1025 " let mut {}_copy = {}.to_vec();",
1026 &list_name, &list_sym
1027 )?;
1028 writeln!(
1029 out,
1030 " let ({}_mask, {}_vec) = base::pack_bitfield(&mut {}_copy);",
1031 &list_name, &list_name, &list_name
1032 )?;
1033 writeln!(
1034 out,
1035 " let {}_ptr = {}_vec.as_ptr();",
1036 &list_name, &list_name
1037 )?;
1038 }
1039 StructField::Switch(name, ..) => {
1040 let ptr_name = format!("{}_ptr", &name);
1041 let ffi_typ = ffi::switch_struct_name(&self.xcb_mod_prefix, req_name, name);
1042 let name = field_name(name);
1043 writeln!(out, " let {} = match {} {{", &ptr_name, name)?;
1044 writeln!(out, " Some(p) => p.ptr as *const {},", &ffi_typ)?;
1045 writeln!(out, " None => std::ptr::null(),")?;
1046 writeln!(out, " }};")?;
1047 }
1048 _ => {}
1049 }
1050 }
1051 writeln!(out, " let cookie = {}(", &ffi_fn_name)?;
1052 writeln!(out, " c.get_raw_conn(),")?;
1053
1054 // FFI request arguments
1055 for f in params.iter() {
1056 match f {
1057 StructField::Field { name, typ, .. } => {
1058 if skip_fields.contains(name) {
1059 continue;
1060 }
1061 let is_pod = self.typ_is_pod(typ);
1062 let is_simple = self.typ_is_simple(typ);
1063 if send_event && name == "event" || is_pod && !is_simple {
1064 let rs_name = field_name(name);
1065 let out = &mut self.rs_buf;
1066 writeln!(out, " {}.base,", &rs_name)?;
1067 } else if is_simple || is_pod {
1068 let ffi_typ = self.ffi_use_type_name(typ);
1069 let mut rs_name = field_name(name);
1070
1071 if let Some(lf) = list_fields.iter().find(|lf| &lf.lenfield == name) {
1072 rs_name = field_name(&lf.name) + "_len";
1073 }
1074 let out = &mut self.rs_buf;
1075 writeln!(out, " {} as {},", &rs_name, &ffi_typ)?;
1076 } else {
1077 let rs_name = field_name(name);
1078 let out = &mut self.rs_buf;
1079 writeln!(out, " {}.ptr", &rs_name)?;
1080 }
1081 }
1082 StructField::Fd(name) => {
1083 let name = field_name(name);
1084 writeln!(&mut self.rs_buf, " {} as i32,", &name)?;
1085 }
1086 StructField::List { name, typ, .. } => {
1087 if send_event && name == "event" {
1088 let out = &mut self.rs_buf;
1089 writeln!(out, " event_ptr")?;
1090 } else {
1091 let rs_name = field_name(name);
1092 let ffi_typ = self.ffi_use_type_name(typ);
1093 let out = &mut self.rs_buf;
1094 writeln!(out, " {}_ptr as *const {},", &rs_name, &ffi_typ)?;
1095 }
1096 }
1097 StructField::ListNoLen { name, typ } => {
1098 let rs_name = field_name(name);
1099 let ffi_typ = self.ffi_use_type_name(typ);
1100 let out = &mut self.rs_buf;
1101 writeln!(out, " {}_len as u32,", &rs_name)?;
1102 writeln!(out, " {}_ptr as *const {},", &rs_name, &ffi_typ)?;
1103 }
1104 StructField::ValueParam {
1105 list_name,
1106 mask_typ,
1107 ..
1108 } => {
1109 let rs_list_name = field_name(list_name);
1110 let typ = self.rs_use_type_name(mask_typ);
1111 let out = &mut self.rs_buf;
1112 writeln!(out, " {}_mask as {},", &rs_list_name, &typ)?;
1113 writeln!(out, " {}_ptr as *const u32,", &rs_list_name)?;
1114 }
1115 StructField::Switch(name, ..) => {
1116 let rs_name = field_name(name);
1117 let out = &mut self.rs_buf;
1118 writeln!(out, " {}_ptr,", &rs_name)?;
1119 }
1120 _ => {}
1121 }
1122 }
1123
1124 let out = &mut self.rs_buf;
1125 writeln!(out, " );")?;
1126 writeln!(out, " {} {{", cookie_name)?;
1127 writeln!(out, " cookie: cookie,")?;
1128 writeln!(out, " conn: c,")?;
1129 writeln!(
1130 out,
1131 " checked: {},",
1132 if checked { "true" } else { "false" }
1133 )?;
1134 writeln!(out, " }}")?;
1135 writeln!(out, " }}")?;
1136 writeln!(out, "}}")?;
1137
1138 Ok(())
1139 }
1140
emit_rs_reply( &mut self, req_name: &str, ffi_cookie: &str, ffi_reply_fn: &str, ffi_reply_typ: &str, rs_cookie: &str, reply: Reply, ) -> io::Result<()>1141 pub fn emit_rs_reply(
1142 &mut self,
1143 req_name: &str,
1144 ffi_cookie: &str,
1145 ffi_reply_fn: &str,
1146 ffi_reply_typ: &str,
1147 rs_cookie: &str,
1148 reply: Reply,
1149 ) -> io::Result<()> {
1150 let rs_reply = type_name(req_name) + "Reply";
1151
1152 {
1153 let out = &mut self.rs_buf;
1154 writeln!(out)?;
1155 writeln!(out, "impl base::CookieSeq for {} {{", &ffi_cookie)?;
1156 writeln!(out, " fn sequence(&self) -> c_uint {{")?;
1157 writeln!(out, " self.sequence")?;
1158 writeln!(out, " }}")?;
1159 writeln!(out, "}}")?;
1160
1161 writeln!(out)?;
1162 writeln!(
1163 out,
1164 "pub type {}<'a> = base::Cookie<'a, {}>;",
1165 &rs_cookie, &ffi_cookie
1166 )?;
1167 writeln!(out)?;
1168
1169 writeln!(out, "impl<'a> {}<'a> {{", &rs_cookie)?;
1170 writeln!(
1171 out,
1172 " pub fn get_reply(self) -> Result<{}, base::ReplyError> {{",
1173 &rs_reply
1174 )?;
1175 writeln!(
1176 out,
1177 " let mut err: *mut xcb_generic_error_t = std::ptr::null_mut();"
1178 )?;
1179 writeln!(
1180 out,
1181 " let err_ptr = if self.checked {{ &mut err }} else {{ std::ptr::null_mut() }};"
1182 )?;
1183 writeln!(out, " let reply = unsafe {{")?;
1184 writeln!(out, " {} {{", &rs_reply)?;
1185 writeln!(out, " ptr: {}(", &ffi_reply_fn)?;
1186 writeln!(out, " self.conn.get_raw_conn(),")?;
1187 writeln!(out, " self.cookie,")?;
1188 writeln!(out, " err_ptr,")?;
1189 writeln!(out, " ),")?;
1190 writeln!(out, " }}")?;
1191 writeln!(out, " }};")?;
1192 writeln!(out, " let checked = self.checked;")?;
1193 writeln!(out, " std::mem::forget(self);")?;
1194 writeln!(out)?;
1195 writeln!(
1196 out,
1197 " match (reply.ptr.is_null(), err.is_null(), checked) {{"
1198 )?;
1199 writeln!(out, " (false, _, false) => Ok(reply),")?;
1200 writeln!(out, " (false, true, true) => Ok(reply),")?;
1201 writeln!(out, " (true, false, _) => Err(base::ReplyError::GenericError(base::GenericError {{ ptr: err }})),")?;
1202 writeln!(
1203 out,
1204 " (true, true, _) => Err(base::ReplyError::NullResponse),"
1205 )?;
1206 writeln!(
1207 out,
1208 " (r, e, c) => unreachable!(\"{{:?}}\", (r, e, c)),"
1209 )?;
1210 writeln!(out, " }}")?;
1211 writeln!(out, " }}")?;
1212 writeln!(out, "}}")?;
1213 }
1214
1215 for f in &reply.fields {
1216 if let StructField::Switch(name, _, cases) = f {
1217 let toplevel = req_name.to_string() + "Reply";
1218 self.emit_rs_switch_typedef(req_name, name, cases, &toplevel, None)?;
1219 }
1220 }
1221
1222 {
1223 let out = &mut self.rs_buf;
1224 writeln!(out)?;
1225 writeln!(
1226 out,
1227 "pub type {} = base::Reply<{}>;",
1228 &rs_reply, &ffi_reply_typ
1229 )?;
1230 writeln!(out)?;
1231 writeln!(out, "impl {} {{", &rs_reply)?;
1232 }
1233
1234 let stru = Struct {
1235 name: req_name.into(),
1236 fields: reply.fields,
1237 doc: reply.doc,
1238 };
1239
1240 self.emit_rs_struct_field_accessors(&stru.name, &stru, "(*self.ptr)", &[], false, true)?;
1241
1242 {
1243 let out = &mut self.rs_buf;
1244 writeln!(out, "}}")?;
1245 }
1246
1247 Ok(())
1248 }
1249 }
1250
has_fd_nfd(fields: &[StructField]) -> bool1251 fn has_fd_nfd(fields: &[StructField]) -> bool {
1252 let mut has_fd = false;
1253 let mut has_nfd = false;
1254
1255 for f in fields.iter() {
1256 match f {
1257 StructField::Field { name, .. } if name == "nfd" => {
1258 has_nfd = true;
1259 }
1260 StructField::Fd(_) => {
1261 has_fd = true;
1262 }
1263 _ => {}
1264 }
1265 }
1266
1267 has_fd && has_nfd
1268 }
1269
has_variable_list(fields: &[StructField]) -> bool1270 fn has_variable_list(fields: &[StructField]) -> bool {
1271 for f in fields.iter() {
1272 match f {
1273 StructField::List { len_expr, ..} => {
1274 let sz = expr_fixed_length(len_expr);
1275 if sz.is_none() {
1276 return true;
1277 }
1278 }
1279 StructField::ListNoLen {..} => {
1280 return true;
1281 }
1282 _ => {}
1283 }
1284 }
1285 false
1286 }
1287
type_name(typ: &str) -> String1288 pub fn type_name(typ: &str) -> String {
1289 match typ {
1290 "CARD8" => "u8".into(),
1291 "CARD16" => "u16".into(),
1292 "CARD32" => "u32".into(),
1293 "CARD64" => "u64".into(),
1294 "INT8" => "i8".into(),
1295 "INT16" => "i16".into(),
1296 "INT32" => "i32".into(),
1297 "BYTE" => "u8".into(),
1298 "BOOL" => "bool".into(),
1299 "char" => "c_char".into(),
1300 "float" => "f32".into(),
1301 "double" => "f64".into(),
1302 typ => tit_cap(typ),
1303 }
1304 }
1305
field_doc_name(f: &StructField) -> Option<String>1306 fn field_doc_name(f: &StructField) -> Option<String> {
1307 match f {
1308 StructField::Field { name, .. } => Some(field_name(name)),
1309 StructField::List { name, .. } => Some(field_name(name)),
1310 StructField::ListNoLen { name, .. } => Some(field_name(name)),
1311 StructField::Fd(name) => Some(field_name(name)),
1312 StructField::ValueParam { list_name, .. } => Some(field_name(list_name)),
1313 _ => None,
1314 }
1315 }
1316
enum_item_name(name: &str, item: &str) -> String1317 pub fn enum_item_name(name: &str, item: &str) -> String {
1318 format!("{}_{}", tit_dig_split(name), tit_dig_split(item)).to_ascii_uppercase()
1319 }
1320
opname(name: &str) -> String1321 pub fn opname(name: &str) -> String {
1322 tit_dig_split(name).to_ascii_uppercase()
1323 }
1324
switch_type_name(req_name: &str, switch_name: &str) -> String1325 pub fn switch_type_name(req_name: &str, switch_name: &str) -> String {
1326 format!("{}{}", tit_cap(req_name), tit_cap(switch_name))
1327 }
1328
request_fn_name(name: &str) -> String1329 pub fn request_fn_name(name: &str) -> String {
1330 let mut res = tit_dig_split(name).to_ascii_lowercase();
1331 if KEYWORDS.contains(&res.as_str()) {
1332 res.push('_');
1333 }
1334 res
1335 }
1336
emit_opcode<Out: Write>(out: &mut Out, name: &str, opcode: i32) -> io::Result<()>1337 pub fn emit_opcode<Out: Write>(out: &mut Out, name: &str, opcode: i32) -> io::Result<()> {
1338 let opname = opname(name);
1339 let num_typ = if opcode < 0 { "i8" } else { "u8" };
1340
1341 writeln!(out)?;
1342 writeln!(out, "pub const {}: {} = {};", &opname, &num_typ, opcode)?;
1343
1344 Ok(())
1345 }
1346
emit_error<Out: Write>(out: &mut Out, ffi_typ: &str, rs_typ: &str) -> io::Result<()>1347 pub fn emit_error<Out: Write>(out: &mut Out, ffi_typ: &str, rs_typ: &str) -> io::Result<()> {
1348 writeln!(out)?;
1349 writeln!(out, "pub struct {} {{", &rs_typ)?;
1350 writeln!(out, " pub base: base::Error<{}>,", &ffi_typ)?;
1351 writeln!(out, "}}")?;
1352
1353 Ok(())
1354 }
1355