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


Reply via email to