-
Notifications
You must be signed in to change notification settings - Fork 222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Schema metadata API #255
Comments
I still keep thinking: "I wonder how far we could get if capnproto-rust had a dynamic reflection API".
But if your procedural macros had access to the dynamic reflection API, that seems like it could maybe be good enough -- all of the annotation lookups would happen during macro expansion. I suppose getting that to work might require splitting things into multiple crates -- one with the capnp generated code, and then one that calls proc macros on it. But that doesn't sound like a fundamental obstacle to me.
Is there any limit to the size of byte strings that appear inside of an attribute like this? |
I'm not sure what do you mean by Dynamic reflection. The link you provided mentions that "Dynamic Reflection API" refers to the interface in Re. literal size limit: can't find anything about that. Doubt that, considering that macros are parsed using the same tokenizer as the rest of the code and considering usage of macros like |
Do you mean in capnproto-c++ or in capnproto-rust? For examples of how to access the schema objects in c++, see https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema-loader-test.c%2B%2B . In particular, there is a method template <typename T>
static inline SchemaType<T> from() { return SchemaType<T>::template fromImpl<T>(); }
// Get the Schema for a particular compiled-in type. It should be possible to do something similar in Rust. |
On the Rust side we still need to start actually including the |
I'm not sure how related this is, but I have been working internally on a proc macro inspired by this PR from last year #157. At the moment its able to generate all necessary set/get/init calls to the code generated builders and readers, and it currently supports most if not all capnp schema data types (including generic types, nested lists, groups, and unions). It does require you to write the rust structs/enums first. Looks something like this:
I was thinking about making a pull request in the next couple weeks once I finish refining it ... would that be helpful/relevant? |
Were you able to find time to advance on the subject ? I don't really know where to start to pick up some of the work already done on |
I just published it here: https://github.com/aikalant/capnp_conv - I still want to write some more/better tests and add a little bit of polish on error messages before I make a PR here though. |
@aikalant any news? |
As of last month, it is possible to get |
This is a follow-up to #246. I was thinking about ways to introduce access to the schema metadata for user code, here are my thoughts. I could try to implement a PR for something mentioned below, but it sounds like a lot of work, not sure if I'll handle that...
The problem
Rust has no reflection, also lots of schema information is not introduced in generated code at all. This information could be used for automatic generation of additional traits or altering runtime behavior. In addition, there is a whole annotation system in Cap'n Proto that seems to be completely ignored currently.
#247 introduced a way to access the whole
CodeGeneratorRequest
that contains all the information about schema. It resolves the problem but it's pretty hard to use. The goal of this issue is to introduce a usable alternative that will attach relevant information fromCodeGeneratorRequest
to relevant places.Since my personal goal is to do a proc-macro based on the capnp reflection information, I'm going to try and design proc-macro friendly solution. Const functions are resolved on compile time, but there seem to be fundamental obstacles to calling just generated const functions from macro expanding part: rust-lang/rfcs#2279. So the only option to make data available is macro attributes: https://doc.rust-lang.org/reference/attributes.html. In the future there could be a separate macro library that will generate const functions based on annotations so the data could be used at runtime too.
Option 1: generate full metadata
The currently generated code doesn't have actual fields for structs, but each field could be associated with a set of functions in generated
Reader
andBuilder
structs. I suggest to add the annotation for Reader and Builder structs that will contain a correspondingNode
fromschema.capnp
, also add annotation to every single field related function that containsField
, theNode
from parent struct and the ordinal number of a field in a struct. Also every annotation should contain a map of id ->Node
to all the dependencies and a enum that specifies the annotated object (Reader
struct,Builder
struct,get_*
function,set_*
function,has_*
function, etc...)Since the annotations are generated, there is no big incentive to make annotations readable. It could be just a single path like
#[capnp::meta(<byte string literal>)]
for every single annotation. The byte string is a Cap'n Proto encoded message calledMacroMetadata
that contains all the information above. There will be a separate library that will provide aTokenStream
to aMacroMetadata
'sReader
. Also every annotation declaration should generate a function that will takeMacroMetadata
and return theOption<Reader>
to the annotation type if that annotation is attached to that object.Option 2: allow custom annotations that generate only needed metadata
Another solution is based on the ability of Cap'n Proto to annotate annotations. That allows for a less invasive and more elegant solution. We could extend
rust.capnp
withgenerateAttributes
that could be used to annotate user defined annotations that will generate macro attributes and/or derives. Annotation parameters would configure the generated macro: path, format, additional info (field id, type, name, deps, etc...) as well as which structs/functions to annotate. Annotated annotation should generate the code that will help extracting useful data from generated attributes.With enough flexibility in
generateAttributes
parameters that could allow integrating with third-party macros. Correct parameters will generate exactly the macro that a third-party crate expects. On the other hand there could be virtually no parameters so it's similar to Option 1 but just for annotated nodes instead of for everything.The text was updated successfully, but these errors were encountered: