Skip to content

Smithy Migration C2j Parity - #3894

Open
sbaluja wants to merge 9 commits into
mainfrom
migration-smithy-2
Open

Smithy Migration C2j Parity #3894
sbaluja wants to merge 9 commits into
mainfrom
migration-smithy-2

Conversation

@sbaluja

@sbaluja sbaluja commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Issue #, if available:

Description of changes:

Check all that applies:

  • Did a review by yourself.
  • Added proper tests to cover this PR. (If tests are not applicable, explain.)
  • Checked if this PR is a breaking (APIs have been changed) change.
  • Checked if this PR will not introduce cross-platform inconsistent behavior.
  • Checked if this PR would require a ReadMe/Wiki update.

Check which platforms you have built SDK on to verify the correctness of this PR.

  • Linux
  • Windows
  • Android
  • MacOS
  • IOS
  • Other Platforms

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Smithy model gen plugin extended

Route raw streaming-payload requests through stream source includes/usings for C2J parity

Delegate InitialResponse header ctor to default ctor for member initialization

Define GetBody() for event-stream input requests to fix link error

Emit member-driven serde source includes in request/result/initial-response for C2J parity

Emit HashingUtils.h in sub-object source for blob members for C2J parity

Emit member doc comment on streaming result payload accessor for C2J parity

Return Optional and fail fast instead of null in streaming-member helpers

Render event-stream input member as shared_ptr with GetBody override for C2J parity

Generate outgoing event-stream unions as EventEncoderStream subclasses for C2J parity

Gate SerializePayload on streaming payload across all protocols for C2J parity

Treat httpPayload blob/string members as streaming for C2J parity

Type modeled exceptions concretely in event-stream unions for C2J parity

Render InitialResponse members from result shape for C2J parity

Map sensitive blobs to CryptoBuffer and document getters to DocumentView for C2J parity

Omit private section for memberless sub-object shapes for C2J parity

Render non-streaming union shapes as sub-object model files for C2J parity

Drop service Errors include from event-stream union header for C2J parity

Remove todo comment

Initialize idempotency-token members with PseudoRandomUUID for C2J parity

Fail fast on unmapped FileKind in serde include/using switches

Sub-object headers must not include the serializer (#include parity)

Split XML InitialResponse serde set from result set (S3 event-stream #include parity)

Remove legacy serde write-hooks; ProtocolTraits owns include/using sets

Fix InitialResponse serde set to exclude AWSStringStream (#include parity)

Route event-stream handler/InitialResponse includes through IncludeSets

Route result/sub-object includes through IncludeSets + serdeIncludes(FileKind)

Make each ProtocolTraits declare serdeIncludes/serdeUsings sets directly

Route request-source includes through IncludeSets + serdeIncludes(FileKind)

Add IncludeSets helper for per-file-kind base includes

Add data-driven serdeIncludes/serdeUsings(FileKind) to ProtocolTraits

Add FileKind enum for per-file-kind serde include sets

Event stream handler serde includes and InitialResponse namespace block

Result source includes per protocol fix

Fix request level includes per protocol

Perfect forwarding for maps/lists codegen fix

Query protocol include fixes, enum name fixes, log tag fixes

Seperate result include headers and add ResponseMetaData for query

Fix stream result member hardcoding to be member shape

Drop redundant URI.h include from request headers for C2J parity

Pin request/result structural surface across all six protocols

Extract ResponseMetadata/requestId in Query/EC2 results

Set HTTP-status-code result members from response code

Render streaming httpPayload results as move-only ResponseStream classes

Classify raw streaming httpPayload results distinct from event streams

Emit HasBeenSet accessors for CBOR results via usesRequiredField hook

Gate Query/EC2 request methods on bindings; keep protected DumpBodyToUrl

Gate REST-XML request methods on header/query bindings

Extract CborProtocolTraits with CBOR-specific types and includes

Gate JSON/REST_JSON request methods on bindings and split target-header + payload body

Generate request class for no-input (Unit) operations to match C2J

Emit URI.h include for requests with query-string or query-protocol methods

Add trait-driven request-contract defaults and widen ProtocolTraits signatures

Add REST_JSON protocol variant distinct from awsJson-RPC

Protocol specific request contract (Headers, URL)

Fix typos/capatilization issues

Remove stale plan references from codegen comments

Thread resolved protocol into ShapeClassifier for a single resolution point

Migrate EventStreamRenderer to ProtocolTraits

Migrate RequestRenderer to ProtocolTraits

Migrate ResultRenderer to ProtocolTraits

Migrate SubObjectRenderer to ProtocolTraits

Add characterization tests pinning generated model output per protocol

Null checks -> Optional

Fix utf-8 bom

Generate event stream model artifacts in Smithy codegen

Add response-side event stream generation (handler, initial response, and
event stream union) plus request augmentation for simplex streaming
operations, closing the gap versus C2J for kinesis SubscribeToShard and
bedrock-runtime streaming operations.

- Add EventStreamRenderer producing the handler and initial-response (with
  serde stubs) and the header-only event stream union, matching C2J which
  emits no .cpp for the union.
- Augment RequestRenderer with HasEventStreamResponse/IsEventStreamRequest
  and the decoder/handler accessors, placing members to match C2J ordering.
- Add event stream detection helpers to ShapeClassifier and event-stream
  serde stub helpers to SerdeStub.
- Restore handler and union documentation to match C2J.
- Deduplicate renderClassDocComment into MemberRenderer and emit the file
  copyright header once from CppWriterDelegator.

Add event-stream augmentation to RequestRenderer

Add EventStream union generation to EventStreamRenderer

Add InitialResponse generation to EventStreamRenderer

Add EventStreamRenderer with handler generation

Add event-stream serde stub helpers to SerdeStub

Add event stream detection helpers to ShapeClassifier

Use FileManifest API in CppWriterDelegator

Enables Smithy's built-in change detection and file tracking
instead of raw Files.writeString().

Deduplicate MemberRenderer public section methods

Extract shared logic into renderMembers(emitHasBeenSet) to eliminate
~100 lines of near-identical code between request and result rendering.

Extract ShapeRenderer interface and per-classification renderers

ModelGenerator is now a thin dispatcher that routes classified shapes to
registered ShapeRenderer implementations. Adding new classification types
(e.g., event streams) requires only a new renderer class, not editing
the orchestrator.

- EnumShapeRenderer, SubObjectRenderer, RequestRenderer, ResultRenderer
- Consolidate isPrimitive() into CppTypeMapper
- Promote writeDocComment/collapseWhitespace to public in MemberRenderer
- No behavioral change to generated output

Fix correctness bugs in model codegen plugin

- Fix typos in EnumRenderer FORBIDDEN_WORDS: co_yeild->co_yield, moduel->module
- Make generateResultSource/Header protocol-aware (was hardcoded to JSON)
- Fix endpoint context param accessor casing (need PascalCase for C++ accessors)
Remove now-dead decapitalize wrapper in MemberRenderer (#0000)

Final cleanup sweep: dead code, include + fieldName consolidation (#0000)

Fail fast on missing streaming payload member in ResultRenderer (#0000)

Clean up inline qualified names and helpers in RequestRenderer (#0000)

Move protocol-invariant request binding queries out of ProtocolTraits (#0000)

Replace MemberRenderer overload ladder with MemberOptions (#0000)

Extract Aws::Model namespace scaffold into ModelFile helper (#0000)

Introduce RenderContext to unify model renderer construction (#0000)

Centralize header include-bracket policy in IncludeSets (#0000)

Extract shared requestId accessor rendering in ResultRenderer (#0000)

Add CppWriter.withNamespace scoped-nesting helper (#0000)

Consolidate C++ identifier helpers into CppNames (#0000)
Route interleaved header namespaces through ModelFile prolog overload

Fold member-driven source includes into protocol union; drop per-member scan (#0000)

Collapse serde source-include switches into per-protocol union (#0000)

Loosen model-plugin include assertions to superset; keep usings exact (#0000)
Move MemberRenderer unit tests to instance API

Migrate model renderers to MemberRenderer instance API

Add MemberRenderer instance API; route static overloads through it

Remove orphaned StructureShape import from CppTypeMapper
@sbaluja
sbaluja force-pushed the migration-smithy-2 branch from 63088da to caf2e2d Compare August 12, 2026 21:35
@sbaluja
sbaluja marked this pull request as ready for review August 12, 2026 21:37
Comment thread crt/aws-crt-cpp
}

@Override
public java.util.List<String> serdeIncludes(FileKind kind) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

idiotmatic java would import java.util.List and then just use List<> in the code. and yeah in c++ its idiotmatic to use std:: instead of using the whole name space. so they different convention wise in this,

* @param namespace the C++ model namespace (e.g. {@code "IAM"}), used for fully-qualified
* log tags in protocols that log during deserialization
*/
void writeResultSerdeImpls(CppWriter writer, String className, StructureShape shape, Model model,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

so something im noticing here is that you pass a CppWriter to each method this kind of gives me the notion that writer should be a member and not a parameter, is it possible to create a accessor like

public interface Renderer {
    Writer writer();

    default void foo() {
        writer().write("foo");
    }

    void bar();
}

public final class MyRenderer implements Renderer {
    private final Writer writer;

    MyRenderer(Writer writer) { this.writer = writer; }

    @Override
    public Writer writer() {
        return writer;
    }

    @Override
    void bar() {
        writer().write("foo");
    }
}

to avoid passing the param each time

for (MemberShape member : resultShape.getAllMembers().values()) {
Shape target = ctx.model().expectShape(member.getTarget());
if (target.isUnionShape() && target.hasTrait(StreamingTrait.class)) {
continue;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not a big fan of continues, or else do something. we could invert the if statement then inside the block add the member to builder, same logically, and avoids the continue

* which dedups, sorts (CaseSensitive) and brackets. Usings are emitted separately by the
* caller via {@link #emitUsings} — this method never touches usings.
*/
static void emitSourceIncludes(CppWriter writer, List<String> base,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

same comment here and it'll be the last time i leave it, it feels like a lot of these classes are along the lines of

class Renderer {
  private Renderer() {}

  Collection<...> PrepareSomeThingsToWrite() {
    // create a list of something to write
  }

  void WriteSomething(Writer writer) {
    var thingsToWrite = PrepareSomeThingsToWrite();
    writer.write(thingsToWrite)
  }
}

i think writer in this cases is member on the top level class, and that the Write functions are public, and the Prepare functions are private.

class Renderer {
  Writer writer;

  private Renderer(Writer writer) {
    writer = writer
  }

  private Collection<...> PrepareSomeThingsToWrite() {
    // create a list of something to write
  }

  public void WriteSomething(Writer writer) {
    var thingsToWrite = PrepareSomeThingsToWrite();
    writer.write(thingsToWrite)
  }
}

writer.write("");

ModelFile.modelNamespace(writer, ctx.namespace(),
() -> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: formatting here seems weird

public void renderHasBeenSetFlags(CppWriter writer) {
for (Map.Entry<String, MemberShape> entry : shape.getAllMembers().entrySet()) {
if (entry.getKey().equals(exclude)) {
continue;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

invert if and avoid the continue

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.

3 participants