Skip to content

Commit 05173fa

Browse files
authored
Merge pull request github#17539 from github/redsun82/rust-codegen-detach
Rust/Codegen: allow to "detach" property emission
2 parents e48e18a + c74b6be commit 05173fa

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed

misc/codegen/generators/rustgen.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,28 @@ def __init__(self, data: schema.Schema):
7272

7373
def _get_class(self, name: str) -> rust.Class:
7474
cls = self._classmap[name]
75+
properties = [
76+
(c, p)
77+
for c, p in _get_properties(cls, self._classmap)
78+
if "rust_skip" not in p.pragmas and not p.synth
79+
]
80+
fields = []
81+
detached_fields = []
82+
for c, p in properties:
83+
if "rust_detach" in p.pragmas:
84+
# only generate detached fields in the actual class defining them, not the derived ones
85+
if c is cls:
86+
# TODO lift this restriction if required (requires change in dbschemegen as well)
87+
assert c.derived or not p.is_single, \
88+
f"property {p.name} in concrete class marked as detached but not optional"
89+
detached_fields.append(_get_field(c, p))
90+
elif not cls.derived:
91+
# for non-detached ones, only generate fields in the concrete classes
92+
fields.append(_get_field(c, p))
7593
return rust.Class(
7694
name=name,
77-
fields=[
78-
_get_field(c, p)
79-
for c, p in _get_properties(cls, self._classmap)
80-
if "rust_skip" not in p.pragmas and not p.synth
81-
] if not cls.derived else [],
95+
fields=fields,
96+
detached_fields=detached_fields,
8297
ancestors=sorted(set(a.name for a in _get_ancestors(cls, self._classmap))),
8398
entry_table=inflection.tableize(cls.name) if not cls.derived else None,
8499
)

misc/codegen/lib/rust.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import dataclasses
22
import re
33
import typing
4+
import inflection
45

56
# taken from https://doc.rust-lang.org/reference/keywords.html
67
keywords = {
@@ -106,12 +107,17 @@ def is_single(self):
106107
def is_label(self):
107108
return self.base_type == "trap::Label"
108109

110+
@property
111+
def singular_field_name(self) -> str:
112+
return inflection.singularize(self.field_name.rstrip("_"))
113+
109114

110115
@dataclasses.dataclass
111116
class Class:
112117
name: str
113118
entry_table: str | None = None
114119
fields: list[Field] = dataclasses.field(default_factory=list)
120+
detached_fields: list[Field] = dataclasses.field(default_factory=list)
115121
ancestors: list[str] = dataclasses.field(default_factory=list)
116122

117123
@property
@@ -128,6 +134,10 @@ def single_field_entries(self) -> dict[str, list[dict]]:
128134
ret.setdefault(f.table_name, []).append(f)
129135
return [{"table_name": k, "fields": v} for k, v in ret.items()]
130136

137+
@property
138+
def has_detached_fields(self) -> bool:
139+
return bool(self.detached_fields)
140+
131141

132142
@dataclasses.dataclass
133143
class ClassList:

misc/codegen/lib/schemadefs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ def __getitem__(self, item):
237237

238238
cpp.add(_Pragma("skip"))
239239

240+
rust.add(_Pragma("detach"))
240241
rust.add(_Pragma("skip_doc_test"))
241242

242243
rust.add(_ParametrizedClassPragma("doc_test_signature", factory=lambda signature: signature))

misc/codegen/templates/rust_classes.mustache

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ pub struct {{name}} {
5959
_unused: ()
6060
}
6161
{{/is_entry}}
62+
{{#has_detached_fields}}
63+
64+
impl {{name}} {
65+
{{#detached_fields}}
66+
pub fn emit_{{singular_field_name}}(id: trap::Label<Self>, {{#is_repeated}}{{^is_unordered}}i: usize, {{/is_unordered}}{{/is_repeated}}value: {{base_type}}, out: &mut trap::Writer) {
67+
out.add_tuple("{{table_name}}", vec![id.into(), {{#is_repeated}}{{^is_unordered}}i.into(), {{/is_unordered}}{{/is_repeated}}value.into()]);
68+
}
69+
{{/detached_fields}}
70+
}
71+
{{/has_detached_fields}}
6272

6373
impl trap::TrapClass for {{name}} {
6474
fn class_name() -> &'static str { "{{name}}" }

0 commit comments

Comments
 (0)