| 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 | |
| 5 | use std::collections::{BTreeMap, HashMap}; |
| 6 | use std::default::Default; |
| 7 | use std::str::FromStr; |
| 8 | use std::{fmt, fs, path::Path as StdPath, path::PathBuf as StdPathBuf}; |
| 9 | |
| 10 | use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer}; |
| 11 | use serde::de::{Deserialize, Deserializer, MapAccess, SeqAccess, Visitor}; |
| 12 | |
| 13 | use crate::bindgen::ir::annotation::AnnotationSet; |
| 14 | use crate::bindgen::ir::path::Path; |
| 15 | use crate::bindgen::ir::repr::ReprAlign; |
| 16 | pub use crate::bindgen::rename::RenameRule; |
| 17 | |
| 18 | pub const VERSION: &str = env!("CARGO_PKG_VERSION" ); |
| 19 | |
| 20 | /// A language type to generate bindings for. |
| 21 | #[derive (Debug, Copy, Clone, PartialEq, Eq)] |
| 22 | pub enum Language { |
| 23 | Cxx, |
| 24 | C, |
| 25 | Cython, |
| 26 | } |
| 27 | |
| 28 | impl FromStr for Language { |
| 29 | type Err = String; |
| 30 | |
| 31 | fn from_str(s: &str) -> Result<Language, Self::Err> { |
| 32 | match s { |
| 33 | "cxx" => Ok(Language::Cxx), |
| 34 | "Cxx" => Ok(Language::Cxx), |
| 35 | "CXX" => Ok(Language::Cxx), |
| 36 | "cpp" => Ok(Language::Cxx), |
| 37 | "Cpp" => Ok(Language::Cxx), |
| 38 | "CPP" => Ok(Language::Cxx), |
| 39 | "c++" => Ok(Language::Cxx), |
| 40 | "C++" => Ok(Language::Cxx), |
| 41 | "c" => Ok(Language::C), |
| 42 | "C" => Ok(Language::C), |
| 43 | "cython" => Ok(Language::Cython), |
| 44 | "Cython" => Ok(Language::Cython), |
| 45 | _ => Err(format!("Unrecognized Language: ' {}'." , s)), |
| 46 | } |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | deserialize_enum_str!(Language); |
| 51 | |
| 52 | impl Language { |
| 53 | pub(crate) fn typedef(self) -> &'static str { |
| 54 | match self { |
| 55 | Language::Cxx | Language::C => "typedef" , |
| 56 | Language::Cython => "ctypedef" , |
| 57 | } |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | /// Controls what type of line endings are used in the generated code. |
| 62 | #[derive (Debug, Clone, Copy)] |
| 63 | #[allow (clippy::upper_case_acronyms)] |
| 64 | #[derive (Default)] |
| 65 | pub enum LineEndingStyle { |
| 66 | /// Use Unix-style linefeed characters |
| 67 | #[default] |
| 68 | LF, |
| 69 | /// Use classic Mac-style carriage-return characters |
| 70 | CR, |
| 71 | /// Use Windows-style carriage-return and linefeed characters |
| 72 | CRLF, |
| 73 | /// Use the native mode for the platform: CRLF on Windows, LF everywhere else. |
| 74 | Native, |
| 75 | } |
| 76 | |
| 77 | impl LineEndingStyle { |
| 78 | pub fn as_str(&self) -> &'static str { |
| 79 | match self { |
| 80 | Self::LF => " \n" , |
| 81 | Self::CR => " \r" , |
| 82 | Self::CRLF => " \r\n" , |
| 83 | Self::Native => { |
| 84 | #[cfg (target_os = "windows" )] |
| 85 | { |
| 86 | Self::CRLF.as_str() |
| 87 | } |
| 88 | #[cfg (not(target_os = "windows" ))] |
| 89 | { |
| 90 | Self::LF.as_str() |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | impl FromStr for LineEndingStyle { |
| 98 | type Err = String; |
| 99 | |
| 100 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 101 | match s.to_lowercase().as_ref() { |
| 102 | "native" => Ok(Self::Native), |
| 103 | "lf" => Ok(Self::LF), |
| 104 | "crlf" => Ok(Self::CRLF), |
| 105 | "cr" => Ok(Self::CR), |
| 106 | _ => Err(format!("Unrecognized line ending style: ' {}'." , s)), |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | deserialize_enum_str!(LineEndingStyle); |
| 112 | |
| 113 | /// A style of braces to use for generating code. |
| 114 | #[derive (Debug, Clone, PartialEq, Eq)] |
| 115 | pub enum Braces { |
| 116 | SameLine, |
| 117 | NextLine, |
| 118 | } |
| 119 | |
| 120 | impl FromStr for Braces { |
| 121 | type Err = String; |
| 122 | |
| 123 | fn from_str(s: &str) -> Result<Braces, Self::Err> { |
| 124 | match s { |
| 125 | "SameLine" => Ok(Braces::SameLine), |
| 126 | "same_line" => Ok(Braces::SameLine), |
| 127 | "NextLine" => Ok(Braces::NextLine), |
| 128 | "next_line" => Ok(Braces::NextLine), |
| 129 | _ => Err(format!("Unrecognized Braces: ' {}'." , s)), |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | deserialize_enum_str!(Braces); |
| 135 | |
| 136 | /// A type of layout to use when generating long lines of code. |
| 137 | #[derive (Debug, Clone, PartialEq, Eq)] |
| 138 | pub enum Layout { |
| 139 | Horizontal, |
| 140 | Vertical, |
| 141 | Auto, |
| 142 | } |
| 143 | |
| 144 | impl FromStr for Layout { |
| 145 | type Err = String; |
| 146 | |
| 147 | fn from_str(s: &str) -> Result<Layout, Self::Err> { |
| 148 | match s { |
| 149 | "Horizontal" => Ok(Layout::Horizontal), |
| 150 | "horizontal" => Ok(Layout::Horizontal), |
| 151 | "Vertical" => Ok(Layout::Vertical), |
| 152 | "vertical" => Ok(Layout::Vertical), |
| 153 | "Auto" => Ok(Layout::Auto), |
| 154 | "auto" => Ok(Layout::Auto), |
| 155 | _ => Err(format!("Unrecognized Layout: ' {}'." , s)), |
| 156 | } |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | deserialize_enum_str!(Layout); |
| 161 | |
| 162 | /// How the comments containing documentation should be styled. |
| 163 | #[derive (Debug, Clone, PartialEq, Eq, Copy)] |
| 164 | pub enum DocumentationStyle { |
| 165 | C, |
| 166 | C99, |
| 167 | Doxy, |
| 168 | Cxx, |
| 169 | Auto, |
| 170 | } |
| 171 | |
| 172 | impl FromStr for DocumentationStyle { |
| 173 | type Err = String; |
| 174 | |
| 175 | fn from_str(s: &str) -> Result<DocumentationStyle, Self::Err> { |
| 176 | match s.to_lowercase().as_ref() { |
| 177 | "c" => Ok(DocumentationStyle::C), |
| 178 | "c99" => Ok(DocumentationStyle::C99), |
| 179 | "cxx" => Ok(DocumentationStyle::Cxx), |
| 180 | "c++" => Ok(DocumentationStyle::Cxx), |
| 181 | "doxy" => Ok(DocumentationStyle::Doxy), |
| 182 | "auto" => Ok(DocumentationStyle::Auto), |
| 183 | _ => Err(format!("Unrecognized documentation style: ' {}'." , s)), |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | deserialize_enum_str!(DocumentationStyle); |
| 189 | |
| 190 | /// How much of the documentation to include in the header file. |
| 191 | #[derive (Debug, Clone, Copy)] |
| 192 | pub enum DocumentationLength { |
| 193 | Short, |
| 194 | Full, |
| 195 | } |
| 196 | |
| 197 | impl FromStr for DocumentationLength { |
| 198 | type Err = String; |
| 199 | |
| 200 | fn from_str(s: &str) -> Result<DocumentationLength, Self::Err> { |
| 201 | match s.to_lowercase().as_ref() { |
| 202 | "short" => Ok(DocumentationLength::Short), |
| 203 | "full" => Ok(DocumentationLength::Full), |
| 204 | _ => Err(format!("Unrecognized documentation style: ' {}'." , s)), |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | deserialize_enum_str!(DocumentationLength); |
| 210 | |
| 211 | /// A style of Style to use when generating structs and enums. |
| 212 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Default)] |
| 213 | pub enum Style { |
| 214 | #[default] |
| 215 | Both, |
| 216 | Tag, |
| 217 | Type, |
| 218 | } |
| 219 | |
| 220 | impl Style { |
| 221 | pub fn generate_tag(self) -> bool { |
| 222 | match self { |
| 223 | Style::Both | Style::Tag => true, |
| 224 | Style::Type => false, |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | pub fn generate_typedef(self) -> bool { |
| 229 | match self { |
| 230 | Style::Both | Style::Type => true, |
| 231 | Style::Tag => false, |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | // https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#styles-of-struct-union-and-enum-declaration |
| 236 | pub fn cython_def(self) -> &'static str { |
| 237 | if self.generate_tag() { |
| 238 | "cdef " |
| 239 | } else { |
| 240 | "ctypedef " |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | impl FromStr for Style { |
| 246 | type Err = String; |
| 247 | |
| 248 | fn from_str(s: &str) -> Result<Style, Self::Err> { |
| 249 | match s { |
| 250 | "Both" => Ok(Style::Both), |
| 251 | "both" => Ok(Style::Both), |
| 252 | "Tag" => Ok(Style::Tag), |
| 253 | "tag" => Ok(Style::Tag), |
| 254 | "Type" => Ok(Style::Type), |
| 255 | "type" => Ok(Style::Type), |
| 256 | _ => Err(format!("Unrecognized Style: ' {}'." , s)), |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | deserialize_enum_str!(Style); |
| 262 | |
| 263 | /// Different item types that we can generate and filter. |
| 264 | #[derive (Debug, Clone, PartialEq, Eq)] |
| 265 | pub enum ItemType { |
| 266 | Constants, |
| 267 | Globals, |
| 268 | Enums, |
| 269 | Structs, |
| 270 | Unions, |
| 271 | Typedefs, |
| 272 | OpaqueItems, |
| 273 | Functions, |
| 274 | } |
| 275 | |
| 276 | impl FromStr for ItemType { |
| 277 | type Err = String; |
| 278 | |
| 279 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 280 | use self::ItemType::*; |
| 281 | Ok(match &*s.to_lowercase() { |
| 282 | "constants" => Constants, |
| 283 | "globals" => Globals, |
| 284 | "enums" => Enums, |
| 285 | "structs" => Structs, |
| 286 | "unions" => Unions, |
| 287 | "typedefs" => Typedefs, |
| 288 | "opaque" => OpaqueItems, |
| 289 | "functions" => Functions, |
| 290 | _ => return Err(format!("Unrecognized Style: ' {}'." , s)), |
| 291 | }) |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | deserialize_enum_str!(ItemType); |
| 296 | |
| 297 | /// Type which specifies the sort order of functions |
| 298 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
| 299 | pub enum SortKey { |
| 300 | Name, |
| 301 | None, |
| 302 | } |
| 303 | |
| 304 | impl FromStr for SortKey { |
| 305 | type Err = String; |
| 306 | |
| 307 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 308 | use self::SortKey::*; |
| 309 | Ok(match &*s.to_lowercase() { |
| 310 | "name" => Name, |
| 311 | "none" => None, |
| 312 | _ => return Err(format!("Unrecognized sort option: ' {}'." , s)), |
| 313 | }) |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | deserialize_enum_str!(SortKey); |
| 318 | |
| 319 | /// Settings to apply when exporting items. |
| 320 | #[derive (Debug, Clone, Deserialize, Default)] |
| 321 | #[serde(rename_all = "snake_case" )] |
| 322 | #[serde(deny_unknown_fields)] |
| 323 | #[serde(default)] |
| 324 | pub struct ExportConfig { |
| 325 | /// A list of additional items not used by exported functions to include in |
| 326 | /// the generated bindings |
| 327 | pub include: Vec<String>, |
| 328 | /// A list of items to not include in the generated bindings |
| 329 | pub exclude: Vec<String>, |
| 330 | /// Table of name conversions to apply to item names |
| 331 | pub rename: HashMap<String, String>, |
| 332 | /// Table of raw strings to prepend to the body of items. |
| 333 | pub pre_body: HashMap<String, String>, |
| 334 | /// Table of raw strings to append to the body of items. |
| 335 | pub body: HashMap<String, String>, |
| 336 | /// A prefix to add before the name of every item |
| 337 | pub prefix: Option<String>, |
| 338 | /// Types of items to generate. |
| 339 | pub item_types: Vec<ItemType>, |
| 340 | /// Whether renaming overrides or extends prefixing. |
| 341 | pub renaming_overrides_prefixing: bool, |
| 342 | /// Mangling configuration. |
| 343 | pub mangle: MangleConfig, |
| 344 | } |
| 345 | |
| 346 | /// Mangling-specific configuration. |
| 347 | #[derive (Debug, Clone, Deserialize, Default)] |
| 348 | #[serde(rename_all = "snake_case" )] |
| 349 | #[serde(deny_unknown_fields)] |
| 350 | #[serde(default)] |
| 351 | pub struct MangleConfig { |
| 352 | /// The rename rule to apply to the type names mangled. |
| 353 | pub rename_types: RenameRule, |
| 354 | /// Remove the underscores used for name mangling. |
| 355 | pub remove_underscores: bool, |
| 356 | } |
| 357 | |
| 358 | impl ExportConfig { |
| 359 | pub(crate) fn should_generate(&self, item_type: ItemType) -> bool { |
| 360 | self.item_types.is_empty() || self.item_types.contains(&item_type) |
| 361 | } |
| 362 | |
| 363 | pub(crate) fn pre_body(&self, path: &Path) -> Option<&str> { |
| 364 | self.pre_body.get(path.name()).map(|s| s.trim_matches(' \n' )) |
| 365 | } |
| 366 | |
| 367 | pub(crate) fn post_body(&self, path: &Path) -> Option<&str> { |
| 368 | self.body.get(path.name()).map(|s| s.trim_matches(' \n' )) |
| 369 | } |
| 370 | |
| 371 | pub(crate) fn rename(&self, item_name: &mut String) { |
| 372 | if let Some(name) = self.rename.get(item_name) { |
| 373 | *item_name = name.clone(); |
| 374 | if self.renaming_overrides_prefixing { |
| 375 | return; |
| 376 | } |
| 377 | } |
| 378 | if let Some(ref prefix) = self.prefix { |
| 379 | item_name.insert_str(0, prefix); |
| 380 | } |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | /// Settings to apply to generated types with layout modifiers. |
| 385 | #[derive (Debug, Default, Clone, Deserialize)] |
| 386 | #[serde(rename_all = "snake_case" )] |
| 387 | #[serde(deny_unknown_fields)] |
| 388 | #[serde(default)] |
| 389 | pub struct LayoutConfig { |
| 390 | /// The way to annotate C types as #[repr(packed)]. |
| 391 | pub packed: Option<String>, |
| 392 | /// The way to annotate C types as #[repr(align(...))]. This is assumed to be a functional |
| 393 | /// macro which takes a single argument (the alignment). |
| 394 | pub aligned_n: Option<String>, |
| 395 | } |
| 396 | |
| 397 | impl LayoutConfig { |
| 398 | pub(crate) fn ensure_safe_to_represent(&self, align: &ReprAlign) -> Result<(), String> { |
| 399 | match (align, &self.packed, &self.aligned_n) { |
| 400 | (ReprAlign::Packed, None, _) => Err("Cannot safely represent #[repr(packed)] type without configured 'packed' annotation." .to_string()), |
| 401 | (ReprAlign::Align(_), _, None) => Err("Cannot safely represent #[repr(aligned(...))] type without configured 'aligned_n' annotation." .to_string()), |
| 402 | _ => Ok(()), |
| 403 | } |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | /// Settings to apply to generated functions. |
| 408 | #[derive (Debug, Clone, Deserialize)] |
| 409 | #[serde(rename_all = "snake_case" )] |
| 410 | #[serde(deny_unknown_fields)] |
| 411 | #[serde(default)] |
| 412 | pub struct FunctionConfig { |
| 413 | /// Optional text to output before each function declaration |
| 414 | pub prefix: Option<String>, |
| 415 | /// Optional text to output after each function declaration |
| 416 | pub postfix: Option<String>, |
| 417 | /// The way to annotation this function as #[must_use] |
| 418 | pub must_use: Option<String>, |
| 419 | /// The way to annotation this function as #[deprecated] without notes |
| 420 | pub deprecated: Option<String>, |
| 421 | /// The way to annotation this function as #[deprecated] with notes |
| 422 | pub deprecated_with_note: Option<String>, |
| 423 | /// The style to layout the args |
| 424 | pub args: Layout, |
| 425 | /// The rename rule to apply to function args |
| 426 | pub rename_args: RenameRule, |
| 427 | /// An optional macro to use when generating Swift function name attributes |
| 428 | pub swift_name_macro: Option<String>, |
| 429 | /// Sort key for functions |
| 430 | pub sort_by: Option<SortKey>, |
| 431 | /// Optional text to output after functions which return `!`. |
| 432 | pub no_return: Option<String>, |
| 433 | } |
| 434 | |
| 435 | impl Default for FunctionConfig { |
| 436 | fn default() -> FunctionConfig { |
| 437 | FunctionConfig { |
| 438 | prefix: None, |
| 439 | postfix: None, |
| 440 | must_use: None, |
| 441 | deprecated: None, |
| 442 | deprecated_with_note: None, |
| 443 | args: Layout::Auto, |
| 444 | rename_args: RenameRule::None, |
| 445 | swift_name_macro: None, |
| 446 | sort_by: None, |
| 447 | no_return: None, |
| 448 | } |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | impl FunctionConfig { |
| 453 | pub(crate) fn prefix(&self, annotations: &AnnotationSet) -> Option<String> { |
| 454 | if let Some(x: Option) = annotations.atom(name:"prefix" ) { |
| 455 | return x; |
| 456 | } |
| 457 | self.prefix.clone() |
| 458 | } |
| 459 | |
| 460 | pub(crate) fn postfix(&self, annotations: &AnnotationSet) -> Option<String> { |
| 461 | if let Some(x: Option) = annotations.atom(name:"postfix" ) { |
| 462 | return x; |
| 463 | } |
| 464 | self.postfix.clone() |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | /// Settings to apply to generated structs. |
| 469 | #[derive (Debug, Default, Clone, Deserialize)] |
| 470 | #[serde(rename_all = "snake_case" )] |
| 471 | #[serde(deny_unknown_fields)] |
| 472 | #[serde(default)] |
| 473 | pub struct StructConfig { |
| 474 | /// The rename rule to apply to the name of struct fields |
| 475 | pub rename_fields: RenameRule, |
| 476 | /// Whether to generate a constructor for the struct (which takes |
| 477 | /// arguments to initialize all the members) |
| 478 | pub derive_constructor: bool, |
| 479 | /// Whether to generate a piecewise equality operator |
| 480 | pub derive_eq: bool, |
| 481 | /// Whether to generate a piecewise inequality operator |
| 482 | pub derive_neq: bool, |
| 483 | /// Whether to generate a less than operator on structs with one field |
| 484 | pub derive_lt: bool, |
| 485 | /// Whether to generate a less than or equal to operator on structs with one field |
| 486 | pub derive_lte: bool, |
| 487 | /// Whether to generate a greater than operator on structs with one field |
| 488 | pub derive_gt: bool, |
| 489 | /// Whether to generate a greater than or equal to operator on structs with one field |
| 490 | pub derive_gte: bool, |
| 491 | /// Whether to generate a ostream serializer for the struct |
| 492 | pub derive_ostream: bool, |
| 493 | /// Whether associated constants should be in the body. Only applicable to |
| 494 | /// non-transparent structs, and in C++-only. |
| 495 | pub associated_constants_in_body: bool, |
| 496 | /// The way to annotate this struct as #[must_use]. |
| 497 | pub must_use: Option<String>, |
| 498 | /// The way to annotation this function as #[deprecated] without notes |
| 499 | pub deprecated: Option<String>, |
| 500 | /// The way to annotation this function as #[deprecated] with notes |
| 501 | pub deprecated_with_note: Option<String>, |
| 502 | } |
| 503 | |
| 504 | impl StructConfig { |
| 505 | pub(crate) fn derive_constructor(&self, annotations: &AnnotationSet) -> bool { |
| 506 | if let Some(x) = annotations.bool("derive-constructor" ) { |
| 507 | return x; |
| 508 | } |
| 509 | self.derive_constructor |
| 510 | } |
| 511 | pub(crate) fn derive_eq(&self, annotations: &AnnotationSet) -> bool { |
| 512 | if let Some(x) = annotations.bool("derive-eq" ) { |
| 513 | return x; |
| 514 | } |
| 515 | self.derive_eq |
| 516 | } |
| 517 | pub(crate) fn derive_neq(&self, annotations: &AnnotationSet) -> bool { |
| 518 | if let Some(x) = annotations.bool("derive-neq" ) { |
| 519 | return x; |
| 520 | } |
| 521 | self.derive_neq |
| 522 | } |
| 523 | pub(crate) fn derive_lt(&self, annotations: &AnnotationSet) -> bool { |
| 524 | if let Some(x) = annotations.bool("derive-lt" ) { |
| 525 | return x; |
| 526 | } |
| 527 | self.derive_lt |
| 528 | } |
| 529 | pub(crate) fn derive_lte(&self, annotations: &AnnotationSet) -> bool { |
| 530 | if let Some(x) = annotations.bool("derive-lte" ) { |
| 531 | return x; |
| 532 | } |
| 533 | self.derive_lte |
| 534 | } |
| 535 | pub(crate) fn derive_gt(&self, annotations: &AnnotationSet) -> bool { |
| 536 | if let Some(x) = annotations.bool("derive-gt" ) { |
| 537 | return x; |
| 538 | } |
| 539 | self.derive_gt |
| 540 | } |
| 541 | pub(crate) fn derive_gte(&self, annotations: &AnnotationSet) -> bool { |
| 542 | if let Some(x) = annotations.bool("derive-gte" ) { |
| 543 | return x; |
| 544 | } |
| 545 | self.derive_gte |
| 546 | } |
| 547 | pub(crate) fn derive_ostream(&self, annotations: &AnnotationSet) -> bool { |
| 548 | if let Some(x) = annotations.bool("derive-ostream" ) { |
| 549 | return x; |
| 550 | } |
| 551 | self.derive_ostream |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | /// Settings to apply to generated enums. |
| 556 | #[derive (Debug, Clone, Deserialize)] |
| 557 | #[serde(rename_all = "snake_case" )] |
| 558 | #[serde(deny_unknown_fields)] |
| 559 | #[serde(default)] |
| 560 | pub struct EnumConfig { |
| 561 | /// The rename rule to apply to the name of enum variants |
| 562 | pub rename_variants: RenameRule, |
| 563 | /// The rename rule to apply to the names of the union fields in C/C++ |
| 564 | /// generated from the Rust enum. Applied before rename_variants |
| 565 | /// rename rule. Defaults to SnakeCase. |
| 566 | pub rename_variant_name_fields: RenameRule, |
| 567 | /// Whether to add a `Sentinel` value at the end of every enum |
| 568 | /// This is useful in Gecko for IPC serialization |
| 569 | pub add_sentinel: bool, |
| 570 | /// Whether the enum variants should be prefixed with the enum name |
| 571 | pub prefix_with_name: bool, |
| 572 | /// Whether to generate static `::X(..)` constructors and `IsX()` |
| 573 | /// methods for tagged enums. |
| 574 | pub derive_helper_methods: bool, |
| 575 | /// Whether to generate `AsX() const` methods for tagged enums. |
| 576 | pub derive_const_casts: bool, |
| 577 | /// Whether to generate `AsX()` methods for tagged enums. |
| 578 | pub derive_mut_casts: bool, |
| 579 | /// The name of the macro to use for `derive_{const,mut}casts`. If custom, you're |
| 580 | /// responsible to provide the necessary header, otherwise `assert` will be |
| 581 | /// used, and `<cassert>` will be included. |
| 582 | pub cast_assert_name: Option<String>, |
| 583 | /// The way to annotation this enum as #[must_use]. |
| 584 | pub must_use: Option<String>, |
| 585 | /// The way to annotation this function as #[deprecated] without notes |
| 586 | pub deprecated: Option<String>, |
| 587 | /// The way to annotation this function as #[deprecated] with notes |
| 588 | pub deprecated_with_note: Option<String>, |
| 589 | /// Whether to generate destructors of tagged enums. |
| 590 | pub derive_tagged_enum_destructor: bool, |
| 591 | /// Whether to generate copy-constructors of tagged enums. |
| 592 | pub derive_tagged_enum_copy_constructor: bool, |
| 593 | /// Whether to generate copy-assignment operators of tagged enums. |
| 594 | /// |
| 595 | /// This is only generated if a copy constructor for the same tagged enum is |
| 596 | /// generated as well. |
| 597 | pub derive_tagged_enum_copy_assignment: bool, |
| 598 | /// Whether to generate a ostream serializer for the struct |
| 599 | pub derive_ostream: bool, |
| 600 | /// Declare the enum as an enum class. |
| 601 | /// Only relevant when targeting C++. |
| 602 | pub enum_class: bool, |
| 603 | /// Whether to generate empty, private default-constructors for tagged |
| 604 | /// enums. |
| 605 | pub private_default_tagged_enum_constructor: bool, |
| 606 | } |
| 607 | |
| 608 | impl Default for EnumConfig { |
| 609 | fn default() -> EnumConfig { |
| 610 | EnumConfig { |
| 611 | rename_variants: RenameRule::None, |
| 612 | rename_variant_name_fields: RenameRule::SnakeCase, |
| 613 | add_sentinel: false, |
| 614 | prefix_with_name: false, |
| 615 | derive_helper_methods: false, |
| 616 | derive_const_casts: false, |
| 617 | derive_mut_casts: false, |
| 618 | cast_assert_name: None, |
| 619 | must_use: None, |
| 620 | deprecated: None, |
| 621 | deprecated_with_note: None, |
| 622 | derive_tagged_enum_destructor: false, |
| 623 | derive_tagged_enum_copy_constructor: false, |
| 624 | derive_tagged_enum_copy_assignment: false, |
| 625 | derive_ostream: false, |
| 626 | enum_class: true, |
| 627 | private_default_tagged_enum_constructor: false, |
| 628 | } |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | impl EnumConfig { |
| 633 | pub(crate) fn add_sentinel(&self, annotations: &AnnotationSet) -> bool { |
| 634 | if let Some(x) = annotations.bool("add-sentinel" ) { |
| 635 | return x; |
| 636 | } |
| 637 | self.add_sentinel |
| 638 | } |
| 639 | pub(crate) fn derive_helper_methods(&self, annotations: &AnnotationSet) -> bool { |
| 640 | if let Some(x) = annotations.bool("derive-helper-methods" ) { |
| 641 | return x; |
| 642 | } |
| 643 | self.derive_helper_methods |
| 644 | } |
| 645 | pub(crate) fn derive_const_casts(&self, annotations: &AnnotationSet) -> bool { |
| 646 | if let Some(x) = annotations.bool("derive-const-casts" ) { |
| 647 | return x; |
| 648 | } |
| 649 | self.derive_const_casts |
| 650 | } |
| 651 | pub(crate) fn derive_mut_casts(&self, annotations: &AnnotationSet) -> bool { |
| 652 | if let Some(x) = annotations.bool("derive-mut-casts" ) { |
| 653 | return x; |
| 654 | } |
| 655 | self.derive_mut_casts |
| 656 | } |
| 657 | pub(crate) fn derive_tagged_enum_destructor(&self, annotations: &AnnotationSet) -> bool { |
| 658 | if let Some(x) = annotations.bool("derive-tagged-enum-destructor" ) { |
| 659 | return x; |
| 660 | } |
| 661 | self.derive_tagged_enum_destructor |
| 662 | } |
| 663 | pub(crate) fn derive_tagged_enum_copy_constructor(&self, annotations: &AnnotationSet) -> bool { |
| 664 | if let Some(x) = annotations.bool("derive-tagged-enum-copy-constructor" ) { |
| 665 | return x; |
| 666 | } |
| 667 | self.derive_tagged_enum_copy_constructor |
| 668 | } |
| 669 | pub(crate) fn derive_tagged_enum_copy_assignment(&self, annotations: &AnnotationSet) -> bool { |
| 670 | if let Some(x) = annotations.bool("derive-tagged-enum-copy-assignment" ) { |
| 671 | return x; |
| 672 | } |
| 673 | self.derive_tagged_enum_copy_assignment |
| 674 | } |
| 675 | pub(crate) fn derive_ostream(&self, annotations: &AnnotationSet) -> bool { |
| 676 | if let Some(x) = annotations.bool("derive-ostream" ) { |
| 677 | return x; |
| 678 | } |
| 679 | self.derive_ostream |
| 680 | } |
| 681 | pub(crate) fn enum_class(&self, annotations: &AnnotationSet) -> bool { |
| 682 | if let Some(x) = annotations.bool("enum-class" ) { |
| 683 | return x; |
| 684 | } |
| 685 | self.enum_class |
| 686 | } |
| 687 | pub(crate) fn private_default_tagged_enum_constructor( |
| 688 | &self, |
| 689 | annotations: &AnnotationSet, |
| 690 | ) -> bool { |
| 691 | if let Some(x) = annotations.bool("private-default-tagged-enum-constructor" ) { |
| 692 | return x; |
| 693 | } |
| 694 | self.private_default_tagged_enum_constructor |
| 695 | } |
| 696 | } |
| 697 | |
| 698 | /// Settings to apply to generated constants. |
| 699 | #[derive (Debug, Clone, Deserialize)] |
| 700 | #[serde(rename_all = "snake_case" )] |
| 701 | #[serde(deny_unknown_fields)] |
| 702 | #[serde(default)] |
| 703 | pub struct ConstantConfig { |
| 704 | /// Whether a generated constant can be a static const in C++ mode. |
| 705 | pub allow_static_const: bool, |
| 706 | /// Whether a generated constant should be constexpr in C++ mode. |
| 707 | pub allow_constexpr: bool, |
| 708 | /// Sort key for constants |
| 709 | pub sort_by: Option<SortKey>, |
| 710 | } |
| 711 | |
| 712 | impl Default for ConstantConfig { |
| 713 | fn default() -> ConstantConfig { |
| 714 | ConstantConfig { |
| 715 | allow_static_const: true, |
| 716 | allow_constexpr: true, |
| 717 | sort_by: None, |
| 718 | } |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | /// Settings for custom macro expansion. |
| 723 | #[derive (Debug, Clone, Deserialize, Default)] |
| 724 | #[serde(rename_all = "snake_case" )] |
| 725 | #[serde(deny_unknown_fields)] |
| 726 | #[serde(default)] |
| 727 | pub struct MacroExpansionConfig { |
| 728 | /// Whether the `bitflags` macro should be expanded. |
| 729 | pub bitflags: bool, |
| 730 | } |
| 731 | |
| 732 | /// Controls which Cargo profile is used for macro expansion. |
| 733 | #[derive (Debug, Copy, Clone, PartialEq, Eq)] |
| 734 | pub enum Profile { |
| 735 | Debug, |
| 736 | Release, |
| 737 | } |
| 738 | |
| 739 | impl FromStr for Profile { |
| 740 | type Err = String; |
| 741 | |
| 742 | fn from_str(s: &str) -> Result<Profile, Self::Err> { |
| 743 | match s { |
| 744 | "debug" | "Debug" => Ok(Profile::Debug), |
| 745 | "release" | "Release" => Ok(Profile::Release), |
| 746 | _ => Err(format!("Unrecognized Profile: ' {}'." , s)), |
| 747 | } |
| 748 | } |
| 749 | } |
| 750 | |
| 751 | deserialize_enum_str!(Profile); |
| 752 | |
| 753 | /// Settings to apply when running `rustc -Zunpretty=expanded` |
| 754 | #[derive (Debug, Clone, Deserialize)] |
| 755 | #[serde(rename_all = "snake_case" )] |
| 756 | #[serde(deny_unknown_fields)] |
| 757 | #[serde(default)] |
| 758 | pub struct ParseExpandConfig { |
| 759 | /// The names of crates to parse with `rustc -Zunpretty=expanded` |
| 760 | pub crates: Vec<String>, |
| 761 | /// Whether to enable all the features when expanding. |
| 762 | pub all_features: bool, |
| 763 | /// Whether to use the default feature set when expanding. |
| 764 | pub default_features: bool, |
| 765 | /// List of features to use when expanding. Combines with `default_features` like in |
| 766 | /// `Cargo.toml`. |
| 767 | pub features: Option<Vec<String>>, |
| 768 | /// Controls whether or not to pass `--release` when expanding. |
| 769 | pub profile: Profile, |
| 770 | } |
| 771 | |
| 772 | impl Default for ParseExpandConfig { |
| 773 | fn default() -> ParseExpandConfig { |
| 774 | ParseExpandConfig { |
| 775 | crates: Vec::new(), |
| 776 | all_features: false, |
| 777 | default_features: true, |
| 778 | features: None, |
| 779 | profile: Profile::Debug, |
| 780 | } |
| 781 | } |
| 782 | } |
| 783 | |
| 784 | // Backwards-compatibility deserializer for ParseExpandConfig. This allows accepting both the |
| 785 | // simple `expand = ["crate"]` and the more complex `expand = {"crates": ["crate"], |
| 786 | // "default_features": false}` format for the `expand` key. |
| 787 | // |
| 788 | // Note that one (major) difference between the two forms is that, for backwards-compatibility |
| 789 | // reasons, the `expand = ["crate"]` form will enable the `--all-features` flag by default while |
| 790 | // the `expand = {"crates": ["crate"]}` form will use the default feature set by default. |
| 791 | fn retrocomp_parse_expand_config_deserialize<'de, D: Deserializer<'de>>( |
| 792 | deserializer: D, |
| 793 | ) -> Result<ParseExpandConfig, D::Error> { |
| 794 | struct ParseExpandVisitor; |
| 795 | |
| 796 | impl<'de> Visitor<'de> for ParseExpandVisitor { |
| 797 | type Value = ParseExpandConfig; |
| 798 | |
| 799 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 800 | formatter.write_str("a map or sequence of string" ) |
| 801 | } |
| 802 | |
| 803 | fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> { |
| 804 | let crates = |
| 805 | <Vec<String> as Deserialize>::deserialize(SeqAccessDeserializer::new(seq))?; |
| 806 | Ok(ParseExpandConfig { |
| 807 | crates, |
| 808 | all_features: true, |
| 809 | default_features: true, |
| 810 | features: None, |
| 811 | profile: Profile::Debug, |
| 812 | }) |
| 813 | } |
| 814 | |
| 815 | fn visit_map<A: MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> { |
| 816 | <ParseExpandConfig as Deserialize>::deserialize(MapAccessDeserializer::new(map)) |
| 817 | } |
| 818 | } |
| 819 | |
| 820 | deserializer.deserialize_any(ParseExpandVisitor) |
| 821 | } |
| 822 | |
| 823 | /// Settings to apply when parsing. |
| 824 | #[derive (Debug, Default, Clone, Deserialize)] |
| 825 | #[serde(rename_all = "snake_case" )] |
| 826 | #[serde(deny_unknown_fields)] |
| 827 | #[serde(default)] |
| 828 | pub struct ParseConfig { |
| 829 | /// Whether to parse dependencies when generating bindings. When this is true, |
| 830 | /// each dependent crate is found using a combination of `cargo metadata` and |
| 831 | /// `Cargo.lock`. To further control this behavior, crates can be whitelisted or |
| 832 | /// blacklisted using `include` and `exclude` respectively. Additionally in cases |
| 833 | /// where crates have types to expose in bindings hidden in macros, a crate can |
| 834 | /// be marked in `expand` and `cargo expand` will be used to expand the macros |
| 835 | /// before parsing. A crate marked in `expand` doesn't need to be added to any |
| 836 | /// whitelist. |
| 837 | pub parse_deps: bool, |
| 838 | /// An optional whitelist of names of crates to parse |
| 839 | pub include: Option<Vec<String>>, |
| 840 | /// The names of crates to not parse |
| 841 | pub exclude: Vec<String>, |
| 842 | /// The configuration options for `rustc -Zunpretty=expanded` |
| 843 | #[serde(deserialize_with = "retrocomp_parse_expand_config_deserialize" )] |
| 844 | pub expand: ParseExpandConfig, |
| 845 | /// Whether to use a new temporary target directory when running `rustc -Zunpretty=expanded`. |
| 846 | /// This may be required for some build processes. |
| 847 | pub clean: bool, |
| 848 | /// List of crate names which generate consts, statics, and fns. By default |
| 849 | /// no dependent crates generate them. |
| 850 | pub extra_bindings: Vec<String>, |
| 851 | } |
| 852 | |
| 853 | impl ParseConfig { |
| 854 | pub(crate) fn should_generate_top_level_item( |
| 855 | &self, |
| 856 | crate_name: &str, |
| 857 | binding_crate_name: &str, |
| 858 | ) -> bool { |
| 859 | if crate_name == binding_crate_name { |
| 860 | // Always generate items for the binding crate. |
| 861 | return true; |
| 862 | } |
| 863 | |
| 864 | self.extra_bindings.iter().any(|dep: &String| dep == crate_name) |
| 865 | } |
| 866 | } |
| 867 | |
| 868 | /// Settings to apply to pointers |
| 869 | #[derive (Debug, Clone, Default, Deserialize)] |
| 870 | #[serde(rename_all = "snake_case" )] |
| 871 | #[serde(deny_unknown_fields)] |
| 872 | #[serde(default)] |
| 873 | pub struct PtrConfig { |
| 874 | /// Optional attribute to apply to pointers that are required to not be null |
| 875 | pub non_null_attribute: Option<String>, |
| 876 | } |
| 877 | |
| 878 | /// Settings specific to Cython bindings. |
| 879 | #[derive (Debug, Clone, Default, Deserialize)] |
| 880 | #[serde(rename_all = "snake_case" )] |
| 881 | #[serde(deny_unknown_fields)] |
| 882 | #[serde(default)] |
| 883 | pub struct CythonConfig { |
| 884 | /// Header specified in the top level `cdef extern from header:` declaration. |
| 885 | pub header: Option<String>, |
| 886 | /// `from module cimport name1, name2, ...` declarations added in the same place |
| 887 | /// where you'd get includes in C. |
| 888 | pub cimports: BTreeMap<String, Vec<String>>, |
| 889 | } |
| 890 | |
| 891 | /// A collection of settings to customize the generated bindings. |
| 892 | #[derive (Debug, Clone, Deserialize)] |
| 893 | #[serde(rename_all = "snake_case" )] |
| 894 | #[serde(deny_unknown_fields)] |
| 895 | #[serde(default)] |
| 896 | pub struct Config { |
| 897 | /// Optional text to output at the beginning of the file |
| 898 | pub header: Option<String>, |
| 899 | /// A list of additional includes to put at the beginning of the generated header |
| 900 | pub includes: Vec<String>, |
| 901 | /// A list of additional system includes to put at the beginning of the generated header |
| 902 | pub sys_includes: Vec<String>, |
| 903 | /// Optional verbatim code added after the include blocks |
| 904 | pub after_includes: Option<String>, |
| 905 | /// Optional text to output at the end of the file |
| 906 | pub trailer: Option<String>, |
| 907 | /// Optional name to use for an include guard |
| 908 | pub include_guard: Option<String>, |
| 909 | /// Add a `#pragma once` guard |
| 910 | pub pragma_once: bool, |
| 911 | /// Generates no includes at all. Overrides all other include options |
| 912 | /// |
| 913 | /// This option is useful when using cbindgen with tools such as python's cffi which |
| 914 | /// doesn't understand include directives |
| 915 | pub no_includes: bool, |
| 916 | /// Optional text to output at major sections to deter manual editing |
| 917 | pub autogen_warning: Option<String>, |
| 918 | /// Include a comment with the version of cbindgen used to generate the file |
| 919 | pub include_version: bool, |
| 920 | /// An optional name for the root namespace. Only applicable when language="C++" |
| 921 | pub namespace: Option<String>, |
| 922 | /// An optional list of namespaces. Only applicable when language="C++" |
| 923 | pub namespaces: Option<Vec<String>>, |
| 924 | /// An optional list of namespaces to declare as using. Only applicable when language="C++" |
| 925 | pub using_namespaces: Option<Vec<String>>, |
| 926 | /// The style to use for braces |
| 927 | pub braces: Braces, |
| 928 | /// The preferred length of a line, used for auto breaking function arguments |
| 929 | pub line_length: usize, |
| 930 | /// The amount of spaces in a tab |
| 931 | pub tab_width: usize, |
| 932 | /// The type of line endings to generate |
| 933 | pub line_endings: LineEndingStyle, |
| 934 | /// The language to output bindings for |
| 935 | pub language: Language, |
| 936 | /// Include preprocessor defines in C bindings to ensure C++ compatibility |
| 937 | pub cpp_compat: bool, |
| 938 | /// The style to declare structs, enums and unions in for C |
| 939 | pub style: Style, |
| 940 | /// Default sort key for functions and constants. |
| 941 | pub sort_by: SortKey, |
| 942 | /// If this option is true `usize` and `isize` will be converted into `size_t` and `ptrdiff_t` |
| 943 | /// instead of `uintptr_t` and `intptr_t` respectively. |
| 944 | pub usize_is_size_t: bool, |
| 945 | /// The configuration options for parsing |
| 946 | pub parse: ParseConfig, |
| 947 | /// The configuration options for exporting |
| 948 | pub export: ExportConfig, |
| 949 | /// The configuration options for macros. |
| 950 | pub macro_expansion: MacroExpansionConfig, |
| 951 | /// The configuration options for type layouts. |
| 952 | pub layout: LayoutConfig, |
| 953 | /// The configuration options for functions |
| 954 | #[serde(rename = "fn" )] |
| 955 | pub function: FunctionConfig, |
| 956 | /// The configuration options for structs |
| 957 | #[serde(rename = "struct" )] |
| 958 | pub structure: StructConfig, |
| 959 | /// The configuration options for enums |
| 960 | #[serde(rename = "enum" )] |
| 961 | pub enumeration: EnumConfig, |
| 962 | /// The configuration options for constants |
| 963 | #[serde(rename = "const" )] |
| 964 | pub constant: ConstantConfig, |
| 965 | /// Preprocessor defines to use when generating #ifdef's for #[cfg] |
| 966 | pub defines: HashMap<String, String>, |
| 967 | /// Include doc comments from Rust as documentation |
| 968 | pub documentation: bool, |
| 969 | /// How documentation comments should be styled. |
| 970 | pub documentation_style: DocumentationStyle, |
| 971 | /// How much of the documentation should be output for each item. |
| 972 | pub documentation_length: DocumentationLength, |
| 973 | /// Configuration options for pointers |
| 974 | #[serde(rename = "ptr" )] |
| 975 | pub pointer: PtrConfig, |
| 976 | /// Only download sources for dependencies needed for the target platform. |
| 977 | /// |
| 978 | /// By default, cbindgen will fetch sources for dependencies used on any platform so that if a |
| 979 | /// type is defined in terms of a type from a dependency on another target (probably behind a |
| 980 | /// `#[cfg]`), cbindgen will be able to generate the appropriate binding as it can see the |
| 981 | /// nested type's definition. However, this makes calling cbindgen slower, as it may have to |
| 982 | /// download a number of additional dependencies. |
| 983 | /// |
| 984 | /// As an example, consider this Cargo.toml: |
| 985 | /// |
| 986 | /// ```toml |
| 987 | /// [target.'cfg(windows)'.dependencies] |
| 988 | /// windows = "0.7" |
| 989 | /// ``` |
| 990 | /// |
| 991 | /// with this declaration in one of the `.rs` files that cbindgen is asked to generate bindings |
| 992 | /// for: |
| 993 | /// |
| 994 | /// ```rust,ignore |
| 995 | /// #[cfg(windows)] |
| 996 | /// pub struct Error(windows::ErrorCode); |
| 997 | /// ``` |
| 998 | /// |
| 999 | /// With the default value (`false`), cbindgen will download the `windows` dependency even when |
| 1000 | /// not compiling for Windows, and will thus be able to generate the binding for `Error` |
| 1001 | /// (behind a `#define`). |
| 1002 | /// |
| 1003 | /// If this value is instead to `true`, cbindgen will _not_ download the `windows` dependency |
| 1004 | /// if it's not compiling for Windows, but will also fail to generate a Windows binding for |
| 1005 | /// `Error` as it does not know the definition for `ErrorCode`. |
| 1006 | /// |
| 1007 | /// The target can be chosen via the `TARGET` environment variable (if used |
| 1008 | /// via the CLI, when ran from a build script cargo sets this variable |
| 1009 | /// appropriately). |
| 1010 | pub only_target_dependencies: bool, |
| 1011 | /// Configuration options specific to Cython. |
| 1012 | pub cython: CythonConfig, |
| 1013 | #[serde(skip)] |
| 1014 | pub(crate) config_path: Option<StdPathBuf>, |
| 1015 | } |
| 1016 | |
| 1017 | impl Default for Config { |
| 1018 | fn default() -> Config { |
| 1019 | Config { |
| 1020 | header: None, |
| 1021 | includes: Vec::new(), |
| 1022 | sys_includes: Vec::new(), |
| 1023 | after_includes: None, |
| 1024 | trailer: None, |
| 1025 | include_guard: None, |
| 1026 | pragma_once: false, |
| 1027 | autogen_warning: None, |
| 1028 | include_version: false, |
| 1029 | no_includes: false, |
| 1030 | namespace: None, |
| 1031 | namespaces: None, |
| 1032 | using_namespaces: None, |
| 1033 | braces: Braces::SameLine, |
| 1034 | line_length: 100, |
| 1035 | tab_width: 2, |
| 1036 | line_endings: LineEndingStyle::default(), |
| 1037 | language: Language::Cxx, |
| 1038 | cpp_compat: false, |
| 1039 | style: Style::default(), |
| 1040 | usize_is_size_t: false, |
| 1041 | sort_by: SortKey::None, |
| 1042 | macro_expansion: Default::default(), |
| 1043 | parse: ParseConfig::default(), |
| 1044 | export: ExportConfig::default(), |
| 1045 | layout: LayoutConfig::default(), |
| 1046 | function: FunctionConfig::default(), |
| 1047 | structure: StructConfig::default(), |
| 1048 | enumeration: EnumConfig::default(), |
| 1049 | constant: ConstantConfig::default(), |
| 1050 | defines: HashMap::new(), |
| 1051 | documentation: true, |
| 1052 | documentation_style: DocumentationStyle::Auto, |
| 1053 | documentation_length: DocumentationLength::Full, |
| 1054 | pointer: PtrConfig::default(), |
| 1055 | only_target_dependencies: false, |
| 1056 | cython: CythonConfig::default(), |
| 1057 | config_path: None, |
| 1058 | } |
| 1059 | } |
| 1060 | } |
| 1061 | |
| 1062 | impl Config { |
| 1063 | pub(crate) fn cpp_compatible_c(&self) -> bool { |
| 1064 | self.language == Language::C && self.cpp_compat |
| 1065 | } |
| 1066 | |
| 1067 | pub(crate) fn include_guard(&self) -> Option<&str> { |
| 1068 | if self.language == Language::Cython { |
| 1069 | None |
| 1070 | } else { |
| 1071 | self.include_guard.as_deref() |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | pub(crate) fn includes(&self) -> &[String] { |
| 1076 | if self.language == Language::Cython { |
| 1077 | &[] |
| 1078 | } else { |
| 1079 | &self.includes |
| 1080 | } |
| 1081 | } |
| 1082 | |
| 1083 | pub(crate) fn sys_includes(&self) -> &[String] { |
| 1084 | if self.language == Language::Cython { |
| 1085 | &[] |
| 1086 | } else { |
| 1087 | &self.sys_includes |
| 1088 | } |
| 1089 | } |
| 1090 | |
| 1091 | pub fn from_file<P: AsRef<StdPath>>(file_name: P) -> Result<Config, String> { |
| 1092 | let config_text = fs::read_to_string(file_name.as_ref()).map_err(|_| { |
| 1093 | format!( |
| 1094 | "Couldn't open config file: {}." , |
| 1095 | file_name.as_ref().display() |
| 1096 | ) |
| 1097 | })?; |
| 1098 | |
| 1099 | let mut config = toml::from_str::<Config>(&config_text) |
| 1100 | .map_err(|e| format!("Couldn't parse config file: {}." , e))?; |
| 1101 | config.config_path = Some(StdPathBuf::from(file_name.as_ref())); |
| 1102 | Ok(config) |
| 1103 | } |
| 1104 | |
| 1105 | pub fn from_root_or_default<P: AsRef<StdPath>>(root: P) -> Config { |
| 1106 | let c = root.as_ref().join("cbindgen.toml" ); |
| 1107 | |
| 1108 | if c.exists() { |
| 1109 | Config::from_file(c).unwrap() |
| 1110 | } else { |
| 1111 | Config::default() |
| 1112 | } |
| 1113 | } |
| 1114 | } |
| 1115 | |