protected abstract void writeOperationSerializerMiddlewareEventStreamSetup()

in codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/integration/HttpBindingProtocolGenerator.java [369:482]


    protected abstract void writeOperationSerializerMiddlewareEventStreamSetup(
            GenerationContext context,
            EventStreamInfo eventStreamInfo
    );

    // Generates operation deserializer middleware that delegates to appropriate deserializers for the error,
    // output shapes for the operation.
    private void generateOperationDeserializerMiddleware(GenerationContext context, OperationShape operation) {
        SymbolProvider symbolProvider = context.getSymbolProvider();
        Model model = context.getModel();
        ServiceShape service = context.getService();

        ApplicationProtocol applicationProtocol = getApplicationProtocol();
        Symbol responseType = applicationProtocol.getResponseType();
        GoWriter goWriter = context.getWriter().get();

        GoStackStepMiddlewareGenerator middleware = GoStackStepMiddlewareGenerator.createDeserializeStepMiddleware(
                ProtocolGenerator.getDeserializeMiddlewareName(operation.getId(), service, getProtocolName()),
                ProtocolUtils.OPERATION_DESERIALIZER_MIDDLEWARE_ID);

        String errorFunctionName = ProtocolGenerator.getOperationErrorDeserFunctionName(
                operation, service, context.getProtocolName());

        middleware.writeMiddleware(goWriter, (generator, writer) -> {
            writer.addUseImports(SmithyGoDependency.FMT);

            writer.write("out, metadata, err = next.$L(ctx, in)", generator.getHandleMethodName());
            writer.write("if err != nil { return out, metadata, err }");
            writer.write("");

            writer.write(goTemplate("""
                    _, span := $T(ctx, "OperationDeserializer")
                    endTimer := startMetricTimer(ctx, "client.call.deserialization_duration")
                    defer endTimer()
                    defer span.End()
                    """, SMITHY_TRACING.func("StartSpan")));

            writer.write("response, ok := out.RawResponse.($P)", responseType);
            writer.openBlock("if !ok {", "}", () -> {
                writer.addUseImports(SmithyGoDependency.SMITHY);
                writer.write(String.format("return out, metadata, &smithy.DeserializationError{Err: %s}",
                        "fmt.Errorf(\"unknown transport type %T\", out.RawResponse)"));
            });
            writer.write("");

            writer.openBlock("if response.StatusCode < 200 || response.StatusCode >= 300 {", "}", () -> {
                writer.write("return out, metadata, $L(response, &metadata)", errorFunctionName);
            });

            Shape outputShape = model.expectShape(operation.getOutput()
                    .orElseThrow(() -> new CodegenException("expect output shape for operation: " + operation.getId()))
            );

            Symbol outputSymbol = symbolProvider.toSymbol(outputShape);

            // initialize out.Result as output structure shape
            writer.write("output := &$T{}", outputSymbol);
            writer.write("out.Result = output");
            writer.write("");

            // Output shape HTTP binding middleware generation
            if (isShapeWithRestResponseBindings(model, operation)) {
                String deserFuncName = ProtocolGenerator.getOperationHttpBindingsDeserFunctionName(
                        outputShape, service, getProtocolName());

                writer.write("err= $L(output, response)", deserFuncName);
                writer.openBlock("if err != nil {", "}", () -> {
                    writer.addUseImports(SmithyGoDependency.SMITHY);
                    writer.write(String.format("return out, metadata, &smithy.DeserializationError{Err: %s}",
                            "fmt.Errorf(\"failed to decode response with invalid Http bindings, %w\", err)"));
                });
                writer.write("");
            }

            Optional<EventStreamInfo> streamInfoOptional = EventStreamIndex.of(model).getOutputInfo(operation);

            // Discard without deserializing the response if the input shape is a stubbed synthetic clone
            // without an archetype.
            if (CodegenUtils.isStubSynthetic(ProtocolUtils.expectOutput(model, operation))
                    && streamInfoOptional.isEmpty()) {
                writer.addUseImports(SmithyGoDependency.IOUTIL);
                writer.openBlock("if _, err = io.Copy(ioutil.Discard, response.Body); err != nil {", "}", () -> {
                    writer.openBlock("return out, metadata, &smithy.DeserializationError{", "}", () -> {
                        writer.write("Err: fmt.Errorf(\"failed to discard response body, %w\", err),");
                    });
                });
            } else {
                boolean hasBodyBinding = HttpBindingIndex.of(model).getResponseBindings(operation).values().stream()
                        .filter(httpBinding -> httpBinding.getLocation() == HttpBinding.Location.DOCUMENT
                                || httpBinding.getLocation() == HttpBinding.Location.PAYLOAD)
                        .anyMatch(httpBinding -> streamInfoOptional.map(esi -> !esi.getEventStreamMember()
                                .equals(httpBinding.getMember())).orElse(true));
                if (hasBodyBinding && streamInfoOptional.isPresent()) {
                    throw new CodegenException("HTTP Binding Protocol unexpected document or payload bindings with "
                            + "output event stream");
                }
                if (hasBodyBinding) {
                    // Output Shape Document Binding middleware generation
                    writeMiddlewareDocumentDeserializerDelegator(context, operation, generator);
                }
            }
            writer.write("");

            writer.write("span.End()");
            writer.write("return out, metadata, err");
        });
        goWriter.write("");

        Set<StructureShape> errorShapes = HttpProtocolGeneratorUtils.generateErrorDispatcher(
                context, operation, responseType, this::writeErrorMessageCodeDeserializer,
                this::getOperationErrors);
        deserializingErrorShapes.addAll(errorShapes);
        deserializeDocumentBindingShapes.addAll(errorShapes);
    }