Re: [PATCH v2 12/16] scripts/qapi: generate high-level Rust bindings
Paolo Bonzini <[email protected]> Tue, 3 Mar 2026 16:55:30 +0100
| Newsgroups | org.nongnu.qemu-rust,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CABgObfYBVbpLfzFiYaCjzTL5zTqynWcUepV=o-AesJJF3jENEQ@mail.gmail.com> |
On Tue, Mar 3, 2026 at 1:31 PM Markus Armbruster <[email protected]> wrote: > >> You replied "In this case it doesn't really matter: public items (such > >> as QAPI enum entries, or struct fields) do not raise the unused warning > >> anyway." > >> > >> What gives us confidence rs_name() will only be used where it doesn't > >> really matter? > > > > The fact that all QAPI type definitions are (more or less by design) public. > > Any particular reason not to use the same 'q_' prefix as in C? The other Rust convention is that you usually have enums in CamelCase (starting with an uppercase letter). "q_" or "Q_" would also trigger a warning, and they would complicate to_camel_case a bit (because the prefix would have to be kept including the underscore). > >> This maps 'foo-0123-bar' to 'Foo_0123Bar'. Intentional? I'd kind of > >> expect 'Foo0123Bar'. > > > > Will fix (it is meant for 0123-45). New version is: > > > > def to_camel_case(value: str) -> str: > > result = '' > > for p in re.split(r'[-_]+', value): > > if not p: > > pass > > elif p[0].isalpha() or (result and result[-1].isalpha()): > > result += p[0].upper() + p[1:] > > else: > > result += '_' + p > > return result > > Maps '0123-45' to '_0123_45'. Is the leading '_' intentional? Yes, because otherwise the output is not an identifier; but it doesn't matter since the input is actually an identifier already and to_camel_case('_0123_45') does give '_0123_45'. In neither case you get the invalid identifier '0123_45'. > I'm fine with not running rustfmt, and I'm fine with running it always > (makes it a hard requirement). Running it sometimes feels like more > trouble than it's worth. Yeah, I will drop it. I changed mcgen to allow removing empty lines in the middle of a declaration, like this: def mcgen(*code: T.Sequence[str], **kwds: object) -> str: ''' Generate ``code`` with ``kwds`` interpolated. Separate positional arguments represent separate segments that could expand to empty strings; empty segments are omitted and no blank lines are introduced at their boundaries. ''' last = len(code) - 1 result = [] for i, s in enumerate(code): if s.startswith('\n'): s = s[1:] if i != last: s = s.rstrip() s = cgen(s, **kwds) if s: result.append(s) return '\n'.join(result) For the case of a single argument, the result is equivalent to the existing implementation: # already checked by current mcgen() if s.startswith('\n'): s = s[1:] # skipped for a single argument if i != last: s = s.rstrip() s = cgen(s, **kwds) if s: result.append(s) # result has zero or a single element, no '\n' added return '\n'.join(result) Paolo