remote-derive: optional as_shared override on derive(ProtoBytes)#294
Merged
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
The generated ProtoBytes impl previously always inherited the trait's as_shared default of None, so a remote bytes newtype - even one wrapping bytes::Bytes - silently took the copy path when encoding into a segmented (Rope) sink, with no way to override from within the derive (the impl is owned by the derive, so a manual one is a coherence error). #[buffa(remote = ..., as_shared = path)] now generates the hook, calling the named path as a free function on the wrapped field (fn(&Remote) -> Option<Bytes>). Absent the key, nothing is generated and the trait default still applies, so existing derives produce identical output. Unknown keys are still rejected, with as_shared added to the error message's key list. Tests cover the default (None), the override returning the wrapped handle (pointer equality), an end-to-end Rope splice through put_shared_bytes_field with parity against a contiguous sink, and the named-field newtype shape. :house: Remote-Dev: homespace
🏠 Remote-Dev: homespace
iainmcgin
force-pushed
the
iain/remote-derive-as-shared
branch
from
July 9, 2026 03:12
67e2618 to
2687ba3
Compare
iainmcgin
marked this pull request as ready for review
July 9, 2026 03:17
iainmcgin
enabled auto-merge
July 9, 2026 03:17
azdagron
approved these changes
Jul 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #284, stacked on
iain/vectored-encode(it needsProtoBytes::as_shared, which only exists there). Retarget tomainif #284 lands first.Problem
buffa-remote-derive(#251) generates the newtype's only permittedProtoBytesimpl, and that impl inherits the trait'sas_shareddefault ofNone. So a remote bytes newtype — even one wrappingbytes::Bytes— always takes the copy path into a segmented (Rope) sink, and the user cannot override it: a manual impl alongside the derive is a coherence error (E0119), and the#[buffa(...)]grammar had no key for it. Output bytes are identical either way, so the missed zero-copy is silent.Change
#[buffa(remote = ..., as_shared = path)]now generates the hook:The path is called as a free function on the wrapped field (
path(&self.0)/path(&self.field)), shapefn(&Remote) -> Option<Bytes>; a signature mismatch is a type error at the generated call site. Absent the key, nothing is generated and the trait default applies — existing derives produce byte-identical output. This mirrors the existingparse_with_overridesmechanism used byProtoBox/MapStorage, in a second mode: an opt-in hook with no default rather than a renamed inherent-method default (the helper's doc now describes both modes).Testing
None; override returns the wrapped handle (pointer equality); end-to-endRopesplice throughput_shared_bytes_field(payload segment pointer-equal to the sourceBytes, byte parity vs a contiguous sink; payload sized2 * DEFAULT_MIN_SEGMENTso the splice threshold can move without breaking the test); named-field newtype shape.bytes_type_custommessage encode into aRopesplices zero-copy; typo'd key and wrong-signature callable both produce legible errors.