Skip to content

Codec Interface to Abstract class, made all paths call parseImpl/writeImpl - #892

Draft
ldintr wants to merge 5 commits into
mainfrom
ldintr-wip
Draft

Codec Interface to Abstract class, made all paths call parseImpl/writeImpl#892
ldintr wants to merge 5 commits into
mainfrom
ldintr-wip

Conversation

@ldintr

@ldintr ldintr commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description:

I didn't like how classes could have a 5 signature parse call a 3 signature overload ignoring some parameters (idr where I saw that, it was outside of obj). I would rather a consistent entry (which I'll use to call throwOnError in the future), and a consistent impl.

Here's a quick look. I may change (or rebase in the future) better javadoc.

Checklist

  • Documented (Code comments, README, etc.)
  • Tested (unit, integration, etc.)

Comments

I noticed I couldn't make this final because sometimes a class overloads it and other times there's no impl

    protected final int writeImpl(@NonNull T item, @NonNull byte[] output, final int startOffset) {
        final BufferedData bufferedData = BufferedData.wrap(output, startOffset, output.length - startOffset);
        try {
            write(item, bufferedData);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
        return (int) bufferedData.position();
    }

It seems like there's a chance they cane become inconsistent

    protected int writeImpl(@NonNull MessageInProtoPackage data, @NonNull byte[] output, final int startOffset) {
        int offset = startOffset;
        // [1] - bytesField
        offset += ProtoArrayWriterTools.writeBytes(output, offset, MessageInProtoPackageSchema.BYTES_FIELD,  data.bytesField(), true);

        // Write unknown fields if there are any
        for (final UnknownField uf : data.getUnknownFields()) {
            final int tag = (uf.field() << TAG_FIELD_OFFSET) | uf.wireType().ordinal();
            offset += ProtoArrayWriterTools.writeUnsignedVarInt(output, offset, tag);
            offset += uf.bytes().writeTo(output, offset);
        }
        return offset - startOffset;
    }

    protected void writeImpl(@NonNull MessageInProtoPackage data, @NonNull final WritableSequentialData out) throws IOException {
            // [1] - bytesField
        writeBytes(out, MessageInProtoPackageSchema.BYTES_FIELD, data.bytesField(), true);

        // Check if not-empty to avoid creating a lambda if there's nothing to write.
        if (!data.getUnknownFields().isEmpty()) {
            data.getUnknownFields().forEach(uf -> {
                final int tag = (uf.field() << TAG_FIELD_OFFSET) | uf.wireType().ordinal();
                out.writeVarInt(tag, false);
                uf.bytes().writeTo(out);
            });
        }
    }

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

JUnit Test Report

   523 files  + 2     523 suites  +2   31s ⏱️ +6s
 1 629 tests +92   1 625 ✅ +92   4 💤 ±0  0 ❌ ±0 
10 847 runs  +92  10 819 ✅ +92  28 💤 ±0  0 ❌ ±0 

Results for commit 6ff8dd8. ± Comparison against base commit 6762bb6.

This pull request removes 6 and adds 98 tests. Note that renamed tests count towards both.
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [1] FLOAT, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49cd30@6df4d8f1, [0.1, 0.5, 100.0], 12, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49cf58@735b1ad2
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [1] STRING, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e4a91b8@230e163b, [string 1, testing here, testing there], com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e4a93e0@7a41f4a7
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [2] BYTES, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e4a9608@7164e54, [010203, ff7f0f, 42da07370bff], com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e4a9830@20040c6e
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [2] DOUBLE, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49d180@88fc9cb, [0.1, 0.5, 100.0, 1.7653472635472653E240], 32, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49d3a8@75693526
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [3] BOOL, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49d5d0@603a34e5, [true, false, false, true, true, true], 6, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49d7f8@160d68b8
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [4] ENUM, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49da20@1d77d9c6, [0, 2, 1], 3, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000005e49dc48@2c5b4b91
com.hedera.pbj.runtime.CodecParseMethodTest ‑ fastEqualsLeavesInputPositionedAtEndOfMessage()
com.hedera.pbj.runtime.CodecParseMethodTest ‑ measureIsNotInflatedByTrailingData()
com.hedera.pbj.runtime.CodecParseMethodTest ‑ measureLeavesInputPositionedAtEndOfMessage()
com.hedera.pbj.runtime.CodecParseMethodTest ‑ parseLeavesInputPositionedAtEndOfMessage()
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [1] FLOAT, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49e6f8@32d3b965, [0.1, 0.5, 100.0], 12, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49e920@7fb2645b
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [1] STRING, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d4aabd0@436103b1, [string 1, testing here, testing there], com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d4aadf8@427128a6
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [2] BYTES, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d4ab020@7a085d02, [010203, ff7f0f, 42da07370bff], com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d4ab248@7842260f
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [2] DOUBLE, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49eb48@25031fd4, [0.1, 0.5, 100.0, 1.7653472635472653E240], 32, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49ed70@54faa040
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [3] BOOL, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49ef98@22195d06, [true, false, false, true, true, true], 6, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49f1c0@1f591b2e
com.hedera.pbj.runtime.ProtoWriterToolsTest ‑ [4] ENUM, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49f3e8@c10f7a8, [0, 2, 1], 3, com.hedera.pbj.runtime.ProtoWriterToolsTest$$Lambda/0x000000001d49f610@64096a41
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Integration Test Report

    428 files  ±0      428 suites  ±0   16m 56s ⏱️ - 4m 9s
115 048 tests ±0  115 048 ✅ ±0  0 💤 ±0  0 ❌ ±0 
115 292 runs  ±0  115 292 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 6ff8dd8. ± Comparison against base commit 6762bb6.

This pull request removes 2 and adds 2 tests. Note that renamed tests count towards both.
com.hedera.pbj.integration.test.ParserNeverWrapsTest ‑ [1] com.hedera.pbj.integration.test.ParserNeverWrapsTest$$Lambda/0x0000000012be6d48@43113fba
com.hedera.pbj.integration.test.ParserNeverWrapsTest ‑ [2] com.hedera.pbj.integration.test.ParserNeverWrapsTest$$Lambda/0x0000000012be6f90@76681fc4
com.hedera.pbj.integration.test.ParserNeverWrapsTest ‑ [1] com.hedera.pbj.integration.test.ParserNeverWrapsTest$$Lambda/0x000000004bc53378@25544039
com.hedera.pbj.integration.test.ParserNeverWrapsTest ‑ [2] com.hedera.pbj.integration.test.ParserNeverWrapsTest$$Lambda/0x000000004bc535c0@6d2f52c3

♻️ This comment has been updated with latest results.

@anthony-swirldslabs anthony-swirldslabs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want to add javadocs to any new protected/public methods. I also left a minor comment. Other than that, the changes look great. Thanks!

Comment on lines -97 to +109
default T parse(@NonNull ReadableSequentialData input, boolean strictMode, boolean parseUnknownFields, int maxDepth)
public final T parse(
@NonNull ReadableSequentialData input, boolean strictMode, boolean parseUnknownFields, int maxDepth)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: I'd go as far as to actually nuke all the overloads that supply default argument values. In the current fix where these methods have simply been made final, the benefit of the code simplification is a bit small to my liking.

return writeImpl(item, output, startOffset);
}

// some classes generate this overload, but not all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come? Our codec generator here in PBJ is supposed to generate them (or not) unconditionally.

Also, you want to add javadocs to any public/protected methods that you introduce here.

@ldintr ldintr Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into it and changed the comment to

CodecWriteByteArrayMethodGenerator.java generates this method for Codecs but not JsonCodecs
We provide a default implementation here so hand written codecs don't need to.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! If that comment in code says exactly this verbatim, then that part would look good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants