-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[protobuf-go/V2 API] Provide an extension mechanism for protoimpl
#1271
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
Comments
MessageInfo
typeprotoimpl
I'm afraid that there is little chance that we will make any of the implementation details in As a specific example, you mention the possibility of a user-provided Please note also that while the |
Thanks for the quick response. Another option would be to release |
I recommend forking As @neild mentioned, there is a potential future where the |
I understand. Clearly removing you ability to refactor internal code is not an option. My previous suggestion comes down to whether I maintain the fork or you do. A Google-maintained implementation fork has the great virtue of having more eyes on it (if But if you can't be persuaded by the compelling argument of having more work to do then I suppose I will have to roll my sleeves up. For reference my current attempt is here: https://github.com/monax/peptide. Thanks for the consideration and speedy responses much appreciated. |
Uh oh!
There was an error while loading. Please reload this page.
tl;dr provide a way to override the mapping (i.e. the
Converter
) between Goreflect
and Protobufprotoreflect
types soprotoimpl
can be reused by other implementationsProblem and background
The
protoreflect
interfaces behaviourally describe protobuf messages and are intended, amongst other things, to allow for custom code generation (for which there is strong demand, but an uncertain future: gogo/protobuf#691). However implementing the entire interface while supporting concurrency and fast path methods is a large undertaking.Many of the low-hanging fruit (e.g. supporting fixed-width named type byte arrays) would need relatively minor changes to existing code to work but custom implementations find they need to fork large amounts of
protobuf-go
in order to reuse the code inprotoimpl
because of the structure ofinternal
packages (see below).An approach for extending the nice functionality provided by
protoimpl
that is conceptually appealing is to embed aMessageState
(*MessageInfo
) object in a struct and interceptprotoreflect.Message
calls where needed before passing along to the underlyingMessageInfo
object (continuing the earlier example, for example, taking a slice over a fixed-width byte array). However this approach does not work becauseMessageInfo.initOnce()
uses the go type to establish aConverter
the implementation of which is hard-coded and will throw errors when it does not see the Go type it expects for the protobuf type it is converting (for instance if a proto message field is not a pointer or a protobytes
field is not a slice).Possible solution
I understand why the
protobuf-go
team has wanted to limit their public API, but I would like to propose that some small incision be made intoprotoimpl
in order to allow dependees to extend it and reuse theprotoimpl
implementation.My hunch is that if the
protoimpl.TypeBuilder
as used by generated code were to take a user-providableConverter
implementation and pass it through theprotoimpl
implementation then that might be enough to reuse most of theprotoimpl
code when serialising to custom types. Another option would be to introduce aConverter() Converter
method to theprotoreflect.Message
or anotherprotoreflect
interface and have that optionally return a custom converter (otherwise returning nil, like withProtoMethods()
), another option still would be to add it to theProtoMethods()
return type. Athough this would not be about 'fast path', it might be convenient since the return type is already weakly typed.Alternatives
I have attempted to only minimally fork
protobuf-go
as suggested by @dsnet here: xen0n/protobuf-gogogo#1 with some success, the results of which are here: https://github.com/monax/peptide/However, as described above, in order to extend the
protoimpl
machinery this is not enough.Another alternative would be to push most of the work of
protoimpl
into the code generator itself and not use go reflection (strong static types and generated methods everywhere). This would probably also provide some performance benefits, but I am happy with protobuf-go performance and I would rather minimise the surface area that needs to be maintained for some simple idiomatic type mappings.Context
Please see my initial ramble on this topic here: xen0n/protobuf-gogogo#1 (comment) including some code examples around how a wrapper/decorator implementation of
protoreflect.Message
on top ofMessageInfo
might work.A further remark having read #526. It may be possible that
protobuf-go
improves its generated code API to 'close the gap' that gogo proto has previously filled, which I am all in favour of, but there are clearly significant trade-offs, legacy, and consistency issues that the present project has to deal with being at the apex of the protobuf ecosystem.I think it could be much more efficient for
protobuf-go
to let a thousand flowers bloom here, provide a slightly larger public API that includes some limited access intoprotoimpl
, while hopefully still allowing you to evolve the internal implementation without making breaking changes. Projects like gogogo and peptide have more freedom to iterate on the code generation side and in doing so we can proof out any interface boundaries aroundprotoimpl
, whichprotobuf-go
itself can make use of to provide a better generated Go API down the line.Work
I had hoped to continue with my 'minimal fork' approach but it looks like the dependency tree will force me to fork many internal packages of
protobuf-go
. I am open to guidance on what would be a good use of time, I could try and implement a proof-of-concept for theConverter
idea against a plain fork forprotobuf-go
if it has any chance of getting accepted. Alternatively I could continue to hack and slash through my minimal fork version, but I'm not convinced I'll end up with something I want to maintain.The text was updated successfully, but these errors were encountered: