Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
23dff57
add #ifdef/#ifndef support to xdr parser and generator
leighmcculloch Mar 17, 2026
342d0c8
remove unnecessary reference on VARIANTS_STR
leighmcculloch Mar 17, 2026
fb663d4
change VARIANTS and VARIANTS_STR from slices to fixed-size arrays
leighmcculloch Mar 17, 2026
c95d121
derive VARIANTS from _VARIANTS using const loop
leighmcculloch Mar 17, 2026
67af0d8
add ifdef support to xdr enum and union generator
leighmcculloch Mar 17, 2026
ab7948a
add ifdef xdr types with lowercase feature names
leighmcculloch Mar 18, 2026
ead1e64
remove `#ifndef` and `#elif` preprocessor directive support
leighmcculloch Mar 18, 2026
b3e3c19
remove `#ifndef`, `#elif` xdr types and related features
leighmcculloch Mar 18, 2026
232cb14
update curr submodule
leighmcculloch Mar 18, 2026
fbe493e
regenerate curr xdr types from updated submodule
leighmcculloch Mar 18, 2026
867e966
remove comments from `_VARIANTS` const slices
leighmcculloch Mar 20, 2026
1ee5ae7
remove test ifdef types and related generated code
leighmcculloch Mar 20, 2026
2a74ddf
remove enable_extra_types and variant_a features
leighmcculloch Mar 20, 2026
027fac6
Merge branch 'main' into ifdef
leighmcculloch Mar 23, 2026
ff3c145
detect unclosed #ifdef in enum/union bodies
leighmcculloch Mar 20, 2026
f1ddabd
fix default on cfg-gated first enum/union member
leighmcculloch Mar 20, 2026
ebeb78e
add tests for inline #ifdef in enum/union bodies
leighmcculloch Mar 20, 2026
b0cfab9
add end-to-end generator tests for #ifdef cfg
leighmcculloch Mar 20, 2026
aa676df
make VARIANTS and VARIANTS_STR loop patterns consistent
leighmcculloch Mar 20, 2026
0908d3c
document feature name lowercasing in CfgExpr::render
leighmcculloch Mar 20, 2026
ddbce41
compute cfg_by_name in single pass over definitions
leighmcculloch Mar 20, 2026
388af14
use HashMap import instead of fully-qualified paths
leighmcculloch Mar 20, 2026
acf952d
regenerate curr and next xdr types
leighmcculloch Mar 20, 2026
ca899cb
add peek_position and extract position_from_byte_offset
leighmcculloch Mar 23, 2026
d3df314
expand generator tests to assert full output snippets
leighmcculloch Mar 23, 2026
aa3dad3
Merge branch 'main' into ifdef
leighmcculloch Mar 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,879 changes: 4,250 additions & 629 deletions src/curr/generated.rs

Large diffs are not rendered by default.

4,879 changes: 4,250 additions & 629 deletions src/next/generated.rs

Large diffs are not rendered by default.

81 changes: 66 additions & 15 deletions xdr-generator-rust/generator/src/generator.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::collections::hash_map::Entry;
use std::collections::HashMap;

use askama::Template;
use xdr_parser::ast::{
Const, Definition, Enum, Struct, StructMember, Typedef, Union, UnionArm, XdrSpec,
Expand All @@ -9,8 +12,8 @@ use crate::naming::{case_value, field_name, source_comment, type_name};
use crate::options::RustOptions;
use crate::output::{
ConstOutput, DefinitionOutput, EnumOutput, EnumStructMemberOutput, GeneratedTemplate,
StructMemberOutput, StructOutput, TypeEnumOutput, TypedefAliasOutput, TypedefNewtypeOutput,
UnionArmOutput, UnionOutput,
StructMemberOutput, StructOutput, TypeEnumEntry, TypeEnumOutput, TypedefAliasOutput,
TypedefNewtypeOutput, UnionArmOutput, UnionOutput,
};
use crate::types::{base_type_ref, resolve_type, size_to_string, type_ref};

Expand Down Expand Up @@ -47,16 +50,40 @@ impl RustGenerator {
.collect();

let mut definitions: Vec<DefinitionOutput> = Vec::new();
let mut cfg_by_name: HashMap<String, Option<String>> = HashMap::new();

for def in spec.all_definitions() {
// Build cfg_by_name for type enum entries in the same pass.
if !matches!(def, Definition::Const(_)) {
let name = type_name(def.name());
let cfg = self.resolve_cfg(def);
match cfg_by_name.entry(name) {
Entry::Vacant(e) => {
e.insert(cfg);
}
Entry::Occupied(mut e) => {
// Same name in multiple cfg branches (e.g. #ifdef/#else)
// means the type is always present, so clear the cfg.
e.insert(None);
}
}
}

let output = self.generate_definition(def);
definitions.push(output);
}

let types: Vec<String> = spec
let types: Vec<TypeEnumEntry> = spec
.type_names_parent_first()
.iter()
.map(|name| type_name(name))
.map(|name| {
let rust_name = type_name(name);
let cfg = cfg_by_name.get(&rust_name).cloned().flatten();
TypeEnumEntry {
name: rust_name,
cfg,
}
})
.collect();

GeneratedTemplate {
Expand All @@ -67,17 +94,27 @@ impl RustGenerator {
}
}

/// Resolve the cfg expression for a definition, rendered as a string.
///
/// This is where additional cfg conditions (e.g. file-based cfg derived
/// from `def.file_index()`) should be combined with the `#ifdef`-derived
/// cfg before rendering. Use `CfgExpr::and()` to combine them.
fn resolve_cfg(&self, def: &Definition) -> Option<String> {
def.cfg().map(|c| c.render())
}

fn generate_definition(&self, def: &Definition) -> DefinitionOutput {
let cfg = self.resolve_cfg(def);
match def {
Definition::Struct(s) => DefinitionOutput::Struct(self.generate_struct(s)),
Definition::Enum(e) => DefinitionOutput::Enum(self.generate_enum(e)),
Definition::Union(u) => DefinitionOutput::Union(self.generate_union(u)),
Definition::Typedef(t) => self.generate_typedef(t),
Definition::Const(c) => DefinitionOutput::Const(self.generate_const(c)),
Definition::Struct(s) => DefinitionOutput::Struct(self.generate_struct(s, cfg)),
Definition::Enum(e) => DefinitionOutput::Enum(self.generate_enum(e, cfg)),
Definition::Union(u) => DefinitionOutput::Union(self.generate_union(u, cfg)),
Definition::Typedef(t) => self.generate_typedef(t, cfg),
Definition::Const(c) => DefinitionOutput::Const(self.generate_const(c, cfg)),
}
}

fn generate_struct(&self, s: &Struct) -> StructOutput {
fn generate_struct(&self, s: &Struct, cfg: Option<String>) -> StructOutput {
let name = type_name(&s.name);
let custom_default = self.options.custom_default_impl.contains(&name);
let custom_str = self.options.custom_str_impl.contains(&name);
Expand Down Expand Up @@ -106,22 +143,25 @@ impl RustGenerator {
is_custom_str: custom_str,
members,
member_names,
cfg,
}
}

fn generate_enum(&self, e: &Enum) -> EnumOutput {
fn generate_enum(&self, e: &Enum, cfg: Option<String>) -> EnumOutput {
let name = type_name(&e.name);
let custom_default = self.options.custom_default_impl.contains(&name);
let custom_str = self.options.custom_str_impl.contains(&name);

let first_uncfg_index = e.members.iter().position(|m| m.cfg.is_none()).unwrap_or(0);
let members: Vec<EnumStructMemberOutput> = e
.members
.iter()
.enumerate()
.map(|(i, m)| EnumStructMemberOutput {
name: type_name(&m.stripped_name),
value: m.value,
is_first: i == 0,
is_default: i == first_uncfg_index,
cfg: m.cfg.as_ref().map(|c| c.render()),
})
.collect();

Expand All @@ -131,10 +171,11 @@ impl RustGenerator {
has_default: !custom_default,
is_custom_str: custom_str,
members,
cfg,
}
}

fn generate_union(&self, u: &Union) -> UnionOutput {
fn generate_union(&self, u: &Union, cfg: Option<String>) -> UnionOutput {
let name = type_name(&u.name);
let custom_default = self.options.custom_default_impl.contains(&name);
let custom_str = self.options.custom_str_impl.contains(&name);
Expand Down Expand Up @@ -172,6 +213,10 @@ impl RustGenerator {
.collect();

let type_kind = if u.is_nested { "NestedUnion" } else { "Union" };
let default_arm_cfg = u
.arms
.first()
.and_then(|a| a.cfg.as_ref().map(|c| c.render()));

UnionOutput {
name,
Expand All @@ -180,17 +225,20 @@ impl RustGenerator {
is_custom_str: custom_str,
discriminant_type,
arms,
cfg,
default_arm_cfg,
}
}

fn generate_typedef(&self, t: &Typedef) -> DefinitionOutput {
fn generate_typedef(&self, t: &Typedef, cfg: Option<String>) -> DefinitionOutput {
let name = type_name(&t.name);

if is_builtin_type(&t.type_) {
return DefinitionOutput::TypedefAlias(TypedefAliasOutput {
name,
source_comment: source_comment(&t.source, "Typedef"),
type_ref: base_type_ref(&t.type_, None),
cfg,
});
}

Expand Down Expand Up @@ -225,10 +273,11 @@ impl RustGenerator {
custom_debug: is_fixed_opaque_type,
custom_display_fromstr: is_fixed_opaque_type && !custom_str && !no_display_fromstr,
custom_schemars: is_fixed_opaque_type && !custom_str && !no_display_fromstr,
cfg,
})
}

fn generate_const(&self, c: &Const) -> ConstOutput {
fn generate_const(&self, c: &Const, cfg: Option<String>) -> ConstOutput {
let value_str = match c.base {
IntBase::Hexadecimal => format!("0x{:X}", c.value),
IntBase::Decimal => c.value.to_string(),
Expand All @@ -238,6 +287,7 @@ impl RustGenerator {
doc_name: type_name(&c.name),
source_comment: source_comment(&c.source, "Const"),
value_str,
cfg,
}
}

Expand Down Expand Up @@ -289,6 +339,7 @@ impl RustGenerator {
type_ref: resolved.as_ref().map(|r| r.type_ref.clone()),
turbofish_type: resolved.as_ref().map(|r| r.turbofish_type.clone()),
serde_as_type: resolved.and_then(|r| r.serde_as_type),
cfg: arm.cfg.as_ref().map(|c| c.render()),
}
})
.collect()
Expand Down
20 changes: 18 additions & 2 deletions xdr-generator-rust/generator/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct StructOutput {
pub is_custom_str: bool,
pub members: Vec<StructMemberOutput>,
pub member_names: String,
pub cfg: Option<String>,
}

pub struct StructMemberOutput {
Expand All @@ -40,12 +41,14 @@ pub struct EnumOutput {
pub has_default: bool,
pub is_custom_str: bool,
pub members: Vec<EnumStructMemberOutput>,
pub cfg: Option<String>,
}

pub struct EnumStructMemberOutput {
pub name: String,
pub value: i32,
pub is_first: bool,
pub is_default: bool,
pub cfg: Option<String>,
}

pub struct UnionOutput {
Expand All @@ -55,6 +58,10 @@ pub struct UnionOutput {
pub is_custom_str: bool,
pub discriminant_type: String,
pub arms: Vec<UnionArmOutput>,
pub cfg: Option<String>,
/// Cfg for the first arm, used to gate the Default impl when the
/// default variant is behind a cfg.
pub default_arm_cfg: Option<String>,
}

pub struct UnionArmOutput {
Expand All @@ -64,12 +71,14 @@ pub struct UnionArmOutput {
pub type_ref: Option<String>,
pub turbofish_type: Option<String>,
pub serde_as_type: Option<String>,
pub cfg: Option<String>,
}

pub struct TypedefAliasOutput {
pub name: String,
pub source_comment: String,
pub type_ref: String,
pub cfg: Option<String>,
}

pub struct TypedefNewtypeOutput {
Expand All @@ -88,15 +97,22 @@ pub struct TypedefNewtypeOutput {
pub custom_debug: bool,
pub custom_display_fromstr: bool,
pub custom_schemars: bool,
pub cfg: Option<String>,
}

pub struct ConstOutput {
pub name: String,
pub doc_name: String,
pub source_comment: String,
pub value_str: String,
pub cfg: Option<String>,
}

pub struct TypeEnumOutput {
pub types: Vec<String>,
pub types: Vec<TypeEnumEntry>,
}

pub struct TypeEnumEntry {
pub name: String,
pub cfg: Option<String>,
}
Loading
Loading