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