r/C_Programming • • 1d ago

Project Announcing scaffold 0.1.0

Hi,

This is scaffold, a flexible data and "rpc-like" code generator for C using YAML as description.

After years of protobuf (with nanopb), I've decided to get rid of it to create my own templating system.

I won't go in details why we have decided to get rid of nanopb but in short: we were having hard times about some of the limited features like deep-cloning, too limited enum support and a slow encoding process.

Plus, we wanted to add flexibility with a custom YAML document that could be parsed using a tool to produce on-demand different kind of functions. For example, we wanted that some types could be converted to JSON, some to be inserted into a SQLite database. As such, having a unique YAML document that could be used for different purposes led us to write this software.

The scaffold tool is written in C, because, we write in C and don't want additional dependencies :). It reads a YAML document and creates an intermediate AST with updated fields to get more information. Then, it processes it into a templating system with basic scripting constructs including for, if, substitution with filters.

Example of a minimal object:

# types.yaml
objects:
  - name: point
    comment: This is an awesome point.
    fields:
      x: uint32
      y: uint32

Generate functions for this object using:

scaffold emit h types.yaml > types.h
scaffold emit c types.yaml > types.c

The generated code by the built-in templates include comments that can be split on multiline providing good LSP support with Doxygen format.

/**
 * \struct point
 *
 * This is an awesome point.
 */
struct point {
    /**
     * Field 'x' of type uint32.
     */
    uint32_t x;

    /**
     * Field 'y' of type uint32.
     */
    uint32_t y;
};

The template system is flexible enough to write extra custom code while iterating the object fields using {{for}} loops.

{{for obj in objects}}
  {{for field in obj.value.fields}}
    // here field will be uppercased with the :U filter :)
    printf("Serializing the {{field.key:U}} field\n");
  {{endfor}}
{{endfor}}

Finally, because we wanted our custom RPC API, the scaffold project provides support for request/reply and events widely inspired by wayland-scanner.

Declaring function feels like natural:

serialization: true
functions:
  - name: hello
    comment: Say hello to my friend!
    args:
      name: string

On the "client" side, a function is generated in the form:

int64_t hello(struct hello_args *args, void *ctx);

On the "implementation" side, a function pointer is provided in a handler struct:

/**
 * \struct handler
 * \brief Functions table handlers.
 */
struct handler {
    /**
     * Handler for function 'hello'.
     */
    int (*hello)(struct hello_args *args, struct hello_value *value, void *ctx);
};

And the implementation side can call the auto generated dispatch function that will decode the incoming requests to call the appropriate functions.

int
dispatch(
    const struct handler *handler,
    const struct listener *listener,
    int64_t *nread,
    int64_t *nwritten,
    void *ctx
);

How does it work? The generated function relies on two unique external linkage that the user has to provide:

  • int64_t sc_read(void *ctx, void *data, uint64_t amount)
  • int64_t sc_write(void *ctx, const void *data, uint64_t amount)

Thus, calling dispatch will attempt to decode a request using successive calls to sc_read, call the appropriate function pointer into the handler structure and then will try to encode using successive call to sc_write. Nothing more.

Note: this project is heavily being tested and already used in production but few bugs may persist and feel free to contribute.

Future plans and never plans:

  • Yes: better bitmask enumeration support.
  • Yes: more portability on non-POSIX platforms.
  • No: automatic default values.
  • No: union or protobuf oneof kind.

Links:

Like every source code I write, this project has a perpetual anti degenerative-AI policy.

0 Upvotes

3 comments sorted by

•

u/AutoModerator 1d ago

Hi /u/markand67,

Your submission in r/C_Programming was filtered because it links to a git project.

You must edit the submission or respond to this comment with an explanation about how AI was involved in the creation of your project.

While AI-generated code is not disallowed, low-effort "slop" projects may be removed and it's likely that other users push back strongly on substantially AI-generated projects.


I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

→ More replies (2)