Skip to content

Commit

Permalink
Add serializers middleware logic for protocol generator awsjson10. (#529
Browse files Browse the repository at this point in the history
)

* Serializers completed code.

* Serializer generation 1st revision.

* Seriailizer generation 2nd revision.

* Fixed the diff error for the Deserializer Stub Code.

* Renamed handleProtocolSetup and created a getSerializerName function.

* Changed getSerializerName to getMiddlewareName to avoid confusion with the JsonSerializerGenerator name function.
  • Loading branch information
nathanhit authored Aug 13, 2024
1 parent a5d3d33 commit 670c64e
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@

import static software.amazon.smithy.go.codegen.ApplicationProtocol.createDefaultHttpApplicationProtocol;
import static software.amazon.smithy.go.codegen.GoWriter.goTemplate;
import static software.amazon.smithy.go.codegen.serde.SerdeUtil.getShapesToSerde;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import software.amazon.smithy.aws.traits.protocols.AwsJson1_0Trait;
import software.amazon.smithy.go.codegen.ApplicationProtocol;
import software.amazon.smithy.go.codegen.GoWriter;
import software.amazon.smithy.go.codegen.SmithyGoDependency;
//import software.amazon.smithy.go.codegen.SmithyGoTypes;
import software.amazon.smithy.go.codegen.integration.ProtocolGenerator;
import software.amazon.smithy.go.codegen.server.protocol.JsonSerializerGenerator;
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
//import software.amazon.smithy.model.shapes.StructureShape;
//import software.amazon.smithy.utils.MapUtils;
import software.amazon.smithy.utils.SmithyInternalApi;


@SmithyInternalApi
public class AwsJson10ProtocolGenerator implements ProtocolGenerator {

@Override
public ShapeId getProtocol() {
return AwsJson1_0Trait.ID;
Expand All @@ -47,11 +49,24 @@ public ApplicationProtocol getApplicationProtocol() {
@Override
public void generateRequestSerializers(GenerationContext context) {
var writer = context.getWriter().get();
var model = context.getModel();
var ops = model.getOperationShapes();
var ops = context.getModel().getOperationShapes();
for (var op : ops) {
requestSerializerCode(op, writer);
var middle = new SerializeMiddleware(context, op, writer);
writer.write(middle.generate());
writer.write("\n");
}
generateSharedSerializers(context, writer, ops);
}

public void generateSharedSerializers(GenerationContext context, GoWriter writer, Set<OperationShape> ops) {
Set<Shape> shared = new HashSet<>();
for (var op : ops) {
Set<Shape> shapes = getShapesToSerde(context.getModel(), context.getModel().expectShape(
op.getInputShape()));
shared.addAll(shapes);
}
var generator = new JsonSerializerGenerator(context.getModel(), context.getSymbolProvider());
writer.write(generator.generate(shared));
}

@Override
Expand Down Expand Up @@ -84,48 +99,6 @@ public void generateProtocolDocumentUnmarshalerUnmarshalDocument(GenerationConte
// TODO
}

private void requestSerializerCode(OperationShape op, GoWriter writer) {
var opName = "awsAwsjson10_serializeOp" + op.toShapeId().getName();;

/*Struct Definition*/
var struct = goTemplate("""
type $L struct{
}
""", opName
);
writer.write(struct);


/* ID Function */
var idFunction = goTemplate("""
func (op *$L) ID() string {
return "OperationSerializer"
}
""", opName
);
writer.write(idFunction);

/* Handle Serialize Function */
var handleFunction = goTemplate(
"""
func (op *$structName:L) HandleSerialize (ctx $context:T, in $input:T, next $handler:T) (
out $output:T, metadata $metadata:T, err error) {
return next.HandleSerialize(ctx, in)
}
""", Map.of(
"context", SmithyGoDependency.CONTEXT.interfaceSymbol("Context"),
"input", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("SerializeInput"),
"handler", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("SerializeHandler"),
"output", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("SerializeOutput"),
"metadata", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("Metadata"),
"structName", opName
));
writer.write(handleFunction);

/* Operation End */
writer.write("\n");
}

private void responseDeserializerCode(OperationShape op, GoWriter writer) {
var opName = "awsAwsjson10_deserializeOp" + op.toShapeId().getName();

Expand All @@ -150,11 +123,11 @@ private void responseDeserializerCode(OperationShape op, GoWriter writer) {
//Handle Serialize Function
var handleFunction = goTemplate(
"""
func (op *$structName:L) HandleDeserialize (ctx $context:T, in $input:T, next $handler:T) (
out $output:T, metadata $metadata:T, err error) {
return out, metadata, err
}
""", Map.of(
func (op *$structName:L) HandleDeserialize (ctx $context:T, in $input:T, next $handler:T) (
out $output:T, metadata $metadata:T, err error) {
return out, metadata, err
}
""", Map.of(
"context", SmithyGoDependency.CONTEXT.interfaceSymbol("Context"),
"input", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("DeserializeInput"),
"handler", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("DeserializeHandler"),
Expand All @@ -167,3 +140,4 @@ private void responseDeserializerCode(OperationShape op, GoWriter writer) {
writer.write("\n");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.smithy.go.codegen.protocol.aws;

import static software.amazon.smithy.go.codegen.GoWriter.goTemplate;
import static software.amazon.smithy.go.codegen.SmithyGoDependency.SMITHY_HTTP_TRANSPORT;
import static software.amazon.smithy.go.codegen.server.protocol.JsonSerializerGenerator.getSerializerName;

import software.amazon.smithy.go.codegen.GoStdlibTypes;
import software.amazon.smithy.go.codegen.GoWriter;
import software.amazon.smithy.go.codegen.SmithyGoDependency;
import software.amazon.smithy.go.codegen.SmithyGoTypes;
import software.amazon.smithy.go.codegen.integration.ProtocolGenerator;
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.utils.MapUtils;

public class SerializeMiddleware {
public static final String CONTENT_TYPE = "application/x-amz-json-1.0";

protected final ProtocolGenerator.GenerationContext ctx;
protected final OperationShape operation;
protected final GoWriter writer;

protected final StructureShape input;
protected final StructureShape output;

private String serialName;

public SerializeMiddleware(
ProtocolGenerator.GenerationContext ctx, OperationShape operation, GoWriter writer
) {
this.ctx = ctx;
this.operation = operation;
this.writer = writer;

this.input = ctx.getModel().expectShape(operation.getInputShape(), StructureShape.class);
this.output = ctx.getModel().expectShape(operation.getOutputShape(), StructureShape.class);
}

public static String getMiddlewareName(OperationShape operation) {
return "awsAwsjson10_serializeOp" + operation.toShapeId().getName();
}

public GoWriter.Writable generate() {
serialName = getMiddlewareName(operation);

return goTemplate("""
type $opName:L struct{
}
func (op *$opName:L) ID() string {
return "OperationSerializer"
}
$handleSerialize:W
""",
MapUtils.of(
"opName", serialName,
"handleSerialize", generateHandleSerialize()
));
}

private GoWriter.Writable generateHandleSerialize() {
return goTemplate(
"""
func (op *$opName:L) HandleSerialize (ctx $context:T, in $input:T, next $handler:T) (
out $output:T, metadata $metadata:T, err error) {
$body:W
return next.HandleSerialize(ctx, in)
}
""", MapUtils.of(
"context", SmithyGoDependency.CONTEXT.interfaceSymbol("Context"),
"input", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("SerializeInput"),
"handler", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("SerializeHandler"),
"output", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("SerializeOutput"),
"metadata", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("Metadata"),
"opName", serialName,
"body", generateHandleSerializeBody())
);
}

private GoWriter.Writable generateHandleSerializeBody() {
return goTemplate("""
$route:W
$serialize:W
""",
MapUtils.of(
"route", handleProtocolSetup(),
"serialize", handlePayload()
));
}

private GoWriter.Writable handleProtocolSetup() {

return goTemplate("""
input, ok := in.Parameters.($input:P)
if !ok {
return out, metadata, $errorf:T("unexpected input type %T", in.Parameters)
}
_ = input
req, ok := in.Request.($request:P)
if !ok {
return out, metadata, $errorf:T("unexpected transport type %T", in.Request)
}
req.Method = $methodPost:T
req.URL.Path = "/"
req.Header.Set("Content-Type", $contentType:S)
req.Header.Set("X-Amz-Target", $target:S)
""",
MapUtils.of(
"input", ctx.getSymbolProvider().toSymbol(input),
"request", SMITHY_HTTP_TRANSPORT.pointableSymbol("Request"),
"methodPost", GoStdlibTypes.Net.Http.MethodPost,
"contentType", CONTENT_TYPE,
"target", ctx.getService().getId().getName() + '.' + operation.getId().getName(),
"errorf", GoStdlibTypes.Fmt.Errorf
));
}

private GoWriter.Writable handlePayload() {
return goTemplate("""
jsonEncoder := $encoder:T()
err = $serialize:L(input, jsonEncoder.Value)
if err != nil {
return out, metadata, &$error:T{Err: err}
}
payload := $reader:T(jsonEncoder.Bytes())
req, err = req.SetStream(payload)
if err != nil {
return out, metadata, &$error:T{Err: err}
}
in.Request = req
""",
MapUtils.of(
"serialize", getSerializerName(input),
"encoder", SmithyGoTypes.Encoding.Json.NewEncoder,
"reader", GoStdlibTypes.Bytes.NewReader,
"error", SmithyGoTypes.Smithy.SerializationError
));
}
}

0 comments on commit 670c64e

Please sign in to comment.