Skip to content

Commit c10d1c8

Browse files
author
luigi
committed
add comments
1 parent 0866dd9 commit c10d1c8

File tree

13 files changed

+295
-13
lines changed

13 files changed

+295
-13
lines changed

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/ServiceStubConfigurations.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ import software.amazon.smithy.model.traits.HttpPayloadTrait
1212
import software.amazon.smithy.model.traits.MediaTypeTrait
1313
import software.amazon.smithy.protocol.traits.Rpcv2CborTrait
1414

15+
/**
16+
* Enumeration of supported media types used by the generated service.
17+
*
18+
* These values define how payloads are encoded/decoded:
19+
* - `CBOR` → Concise Binary Object Representation
20+
* - `JSON` → JSON encoding
21+
* - `PLAIN_TEXT` → Text/plain
22+
* - `OCTET_STREAM` → Binary data
23+
* - `ANY` → Fallback for arbitrary content types
24+
*/
1525
enum class MediaType(val value: String) {
1626
CBOR("CBOR"),
1727
JSON("JSON"),
@@ -57,6 +67,12 @@ enum class MediaType(val value: String) {
5767
}
5868
}
5969

70+
/**
71+
* Enumeration of supported service frameworks for generated stubs.
72+
*
73+
* Currently only supports:
74+
* - `KTOR`: Generates Ktor-based service stubs
75+
*/
6076
enum class ServiceFramework(val value: String) {
6177
KTOR("ktor"),
6278
;

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/ServiceStubGenerator.kt

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,29 @@ import software.amazon.smithy.kotlin.codegen.core.withBlock
1010
import software.amazon.smithy.kotlin.codegen.core.withInlineBlock
1111
import software.amazon.smithy.model.knowledge.TopDownIndex
1212

13+
/**
14+
* Interface representing a generator that produces service stubs (boilerplate code) for a Smithy service.
15+
*/
1316
internal interface ServiceStubGenerator {
17+
/**
18+
* Render the stub code into the target files.
19+
*/
1420
fun render()
1521
}
1622

23+
/**
24+
* Abstract base class for generating service stubs.
25+
*
26+
* Provides a framework for generating common service artifacts such as:
27+
* - Configuration (`ServiceFrameworkConfig.kt`)
28+
* - Framework bootstrap (`ServiceFramework.kt`)
29+
* - Plugins, utils, authentication, validators
30+
* - Operation handlers and routing
31+
* - Main launcher (`Main.kt`)
32+
*
33+
* Concrete subclasses must implement abstract methods for framework-specific
34+
* code (e.g., Ktor).
35+
*/
1736
internal abstract class AbstractStubGenerator(
1837
val ctx: GenerationContext,
1938
val delegator: KotlinDelegator,
@@ -27,6 +46,10 @@ internal abstract class AbstractStubGenerator(
2746

2847
val pkgName = ctx.settings.pkg.name
2948

49+
/**
50+
* Render all service stub files by invoking the component renderers.
51+
* This acts as the main entrypoint for code generation.
52+
*/
3053
final override fun render() {
3154
renderServiceFrameworkConfig()
3255
renderServiceFramework()
@@ -39,7 +62,16 @@ internal abstract class AbstractStubGenerator(
3962
renderMainFile()
4063
}
4164

42-
/** Emits the `ServiceFrameworkConfig.kt` file. */
65+
/**
66+
* Generate the service configuration file (`ServiceFrameworkConfig.kt`).
67+
*
68+
* Defines enums for:
69+
* - `LogLevel`: Logging verbosity levels
70+
* - `ServiceEngine`: Available server engines (Netty, CIO, Jetty)
71+
*
72+
* Provides a singleton `ServiceFrameworkConfig` object that stores runtime
73+
* settings such as port, engine, region, timeouts, and log level.
74+
*/
4375
protected fun renderServiceFrameworkConfig() {
4476
delegator.useFileWriter("ServiceFrameworkConfig.kt", "${ctx.settings.pkg.name}.config") { writer ->
4577
writer.withBlock("internal enum class LogLevel(val value: String) {", "}") {
@@ -143,7 +175,12 @@ internal abstract class AbstractStubGenerator(
143175
}
144176
}
145177

146-
/** Emits ServiceFramework.kt and other engine bootstrap code. */
178+
/**
179+
* Generate the service framework interface and bootstrap (`ServiceFramework.kt`).
180+
*
181+
* Declares a common `ServiceFramework` interface with lifecycle methods and
182+
* delegates framework-specific implementation details to subclasses.
183+
*/
147184
protected fun renderServiceFramework() {
148185
delegator.useFileWriter("ServiceFramework.kt", "${ctx.settings.pkg.name}.framework") { writer ->
149186

@@ -157,27 +194,36 @@ internal abstract class AbstractStubGenerator(
157194
}
158195
}
159196

197+
/** Render the specific server framework implementation (e.g., Ktor). */
160198
protected abstract fun renderServerFrameworkImplementation(writer: KotlinWriter)
161199

162-
/** Emits content-type guards, error handler plugins, … */
200+
/** Generate service plugins such as content-type guards, error handlers, etc. */
163201
protected abstract fun renderPlugins()
164202

165-
/** Emits utils. */
203+
/** Generate supporting utility classes and functions. */
166204
protected abstract fun renderUtils()
167205

168-
/** Auth interfaces & installers (bearer, IAM, …). */
206+
/** Generate authentication module interfaces and installers (e.g., bearer auth, SigV4, SigV4A). */
169207
protected abstract fun renderAuthModule()
170208

171-
/** Request-level Smithy constraint validators. */
209+
/** Generate request-level constraint validators for Smithy model constraints. */
172210
protected abstract fun renderConstraintValidators()
173211

174-
/** One handler file per Smithy operation. */
212+
/** Generate a request handler for each Smithy operation. */
175213
protected abstract fun renderPerOperationHandlers()
176214

177-
/** Route table that maps operations runtime endpoints. */
215+
/** Generate the route table that maps Smithy operations to runtime endpoints. */
178216
protected abstract fun renderRouting()
179217

180-
/** Writes the top-level `Main.kt` launcher. */
218+
/**
219+
* Generate the top-level `Main.kt` launcher file.
220+
*
221+
* This file provides the `main()` entrypoint:
222+
* - Parses command-line arguments
223+
* - Applies defaults for configuration values
224+
* - Initializes the `ServiceFrameworkConfig`
225+
* - Starts the appropriate service framework
226+
*/
181227
protected fun renderMainFile() {
182228
val portName = "port"
183229
val engineFactoryName = "engineFactory"

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/constraints/ConstraintGenerator.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ import software.amazon.smithy.model.shapes.StructureShape
1010
import software.amazon.smithy.model.traits.RequiredTrait
1111
import kotlin.collections.iterator
1212

13+
/**
14+
* Generates validation code for request constraints on Smithy operation inputs.
15+
*
16+
* For a given [operation], this generator traverses the input structure and:
17+
* - Recursively inspects members of structures and lists.
18+
* - Applies trait-based validations (e.g., required, length, range).
19+
* - Emits Kotlin validation functions that check constraints at runtime.
20+
*
21+
* Output is written into a `<Operation>RequestConstraints.kt` file in the generated `constraints` package.
22+
*/
1323
internal class ConstraintGenerator(
1424
val ctx: GenerationContext,
1525
val operation: OperationShape,
@@ -21,9 +31,23 @@ internal class ConstraintGenerator(
2131
val opName = operation.id.name
2232
val pkgName = ctx.settings.pkg.name
2333

34+
/**
35+
* Entry point for emitting validation code for the operation’s request type.
36+
* Delegates to [renderRequestConstraintsValidation].
37+
*/
2438
fun render() {
2539
renderRequestConstraintsValidation()
2640
}
41+
42+
/**
43+
* Recursively generates validation code for a given [memberShape].
44+
*
45+
* - If the target is a list, iterates over elements and validates them.
46+
* - If the target is a structure, recursively validates its members.
47+
* - For each trait (on the member or its target), invokes the matching trait generator.
48+
* - `@required` traits are always enforced.
49+
* - Other traits are wrapped in a null check before validation.
50+
*/
2751
private fun generateConstraintValidations(prefix: String, memberShape: MemberShape, writer: KotlinWriter) {
2852
val targetShape = ctx.model.expectShape(memberShape.target)
2953

@@ -59,6 +83,12 @@ internal class ConstraintGenerator(
5983
}
6084
}
6185

86+
/**
87+
* Writes the top-level validation function for the operation’s input type.
88+
*
89+
* Inside, it calls [generateConstraintValidations] for each input member,
90+
* ensuring all modeled constraints are enforced.
91+
*/
6292
private fun renderRequestConstraintsValidation() {
6393
delegator.useFileWriter("${opName}RequestConstraints.kt", "$pkgName.constraints") { writer ->
6494
val inputShape = ctx.model.expectShape(operation.input.get())

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/constraints/ConstraintUtilsGenerator.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ import software.amazon.smithy.kotlin.codegen.core.KotlinDelegator
55
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
66
import software.amazon.smithy.kotlin.codegen.core.withBlock
77

8+
/**
9+
* Generates utility functions to support constraint validation for Smithy models.
10+
*
11+
* This generator emits reusable helpers that can be called from operation-specific
12+
* validation code (e.g., generated by [ConstraintGenerator]). These helpers enforce
13+
* common traits like `@length` and `@uniqueItems`.
14+
*
15+
* Output is written into a `utils.kt` file under the generated `constraints` package.
16+
*/
817
internal class ConstraintUtilsGenerator(
918
val ctx: GenerationContext,
1019
val delegator: KotlinDelegator,
@@ -20,6 +29,16 @@ internal class ConstraintUtilsGenerator(
2029
}
2130
}
2231

32+
/**
33+
* Emits the `sizeOf()` function.
34+
*
35+
* This utility computes a generalized "size" for multiple types:
36+
* - Collections, arrays, maps → `size`
37+
* - Strings → Unicode code point count
38+
* - Byte arrays → length
39+
*
40+
* Any unsupported type will throw an `IllegalArgumentException`.
41+
*/
2342
private fun renderLengthTraitUtils(writer: KotlinWriter) {
2443
writer.withBlock("internal fun sizeOf(value: Any?): Long = when (value) {", "}") {
2544
write("is Collection<*> -> value.size.toLong()")
@@ -34,6 +53,16 @@ internal class ConstraintUtilsGenerator(
3453
}
3554
}
3655

56+
/**
57+
* Emits the `hasAllUniqueElements()` function.
58+
*
59+
* This utility checks if a list contains only unique elements, where uniqueness
60+
* is defined by deep structural equality:
61+
* - Primitive wrappers (String, Boolean, Number, Instant) → compared by value
62+
* - Byte arrays → compared by contents
63+
* - Lists → recursively compared element by element
64+
* - Maps → recursively compared entries by key/value
65+
*/
3766
private fun renderUniqueItemsTraitUtils(writer: KotlinWriter) {
3867
writer.withBlock("internal fun hasAllUniqueElements(elements: List<Any?>): Boolean {", "}") {
3968
withBlock("class Wrapped(private val v: Any?) {", "}") {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/ktor/Authentication.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ import software.amazon.smithy.kotlin.codegen.core.withBlock
77
import software.amazon.smithy.kotlin.codegen.model.getTrait
88
import software.amazon.smithy.kotlin.codegen.service.ServiceTypes
99

10+
/**
11+
* Writes Ktor-based authentication support classes and configuration
12+
* for a generated service.
13+
*
14+
* This generates three files:
15+
* 1. UserPrincipal.kt → Represents the authenticated user.
16+
* 2. Validation.kt → Provides bearer token validation logic.
17+
* 3. Authentication.kt → Configures authentication providers in Ktor.
18+
*/
1019
internal fun KtorStubGenerator.writeAuthentication() {
1120
delegator.useFileWriter("UserPrincipal.kt", "$pkgName.auth") { writer ->
1221
writer.withBlock("public data class UserPrincipal(", ")") {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/ktor/AuthenticationAWS.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ import software.amazon.smithy.kotlin.codegen.core.withBlock
77
import software.amazon.smithy.kotlin.codegen.core.withInlineBlock
88
import software.amazon.smithy.kotlin.codegen.lang.KotlinTypes
99

10+
/**
11+
* Writes AWS-specific authentication support for Ktor service stubs.
12+
*
13+
* This generates the following files:
14+
* - AWSValidation.kt → Stub stores for SigV4 credentials and SigV4A public keys.
15+
* - AWSSigV4.kt → Ktor authentication provider and verifier for AWS Signature V4 (HMAC).
16+
* - AWSSigV4A.kt → Ktor authentication provider and verifier for AWS Signature V4A (ECDSA).
17+
*/
1018
internal fun KtorStubGenerator.writeAWSAuthentication() {
1119
delegator.useFileWriter("AWSValidation.kt", "$pkgName.auth") { writer ->
1220
writer.withBlock("internal object SigV4CredentialStore {", "}") {
@@ -213,6 +221,10 @@ internal fun KtorStubGenerator.writeAWSAuthentication() {
213221
}
214222
}
215223

224+
/**
225+
* Extracts and parses AWS authentication header information
226+
* (Credential, SignedHeaders, Signature) from a request.
227+
*/
216228
private fun retrieveAuthInformation(writer: KotlinWriter, algorithm: String) {
217229
writer.write("val authHeader = call.request.#T(#T.Authorization) ?: return null", RuntimeTypes.KtorServerRouting.requestHeader, RuntimeTypes.KtorServerHttp.HttpHeaders)
218230
.write("if (!authHeader.startsWith(#S, ignoreCase = true)) return null", algorithm)
@@ -229,6 +241,9 @@ private fun retrieveAuthInformation(writer: KotlinWriter, algorithm: String) {
229241
.write("val accessKeyId = credential.substringBefore(#S).takeIf { it.matches(Regex(#S)) } ?: return null", "/", "^[A-Z0-9]{16,128}$")
230242
}
231243

244+
/**
245+
* Validates signing date against request scope date and clock skew.
246+
*/
232247
private fun authDateValidation(writer: KotlinWriter) {
233248
writer.write("val rawXAmzDate = call.request.#T(#S)", RuntimeTypes.KtorServerRouting.requestHeader, "X-Amz-Date")
234249
.write("val rawHttpDate = call.request.#T(#T.Date)", RuntimeTypes.KtorServerRouting.requestHeader, RuntimeTypes.KtorServerHttp.HttpHeaders)
@@ -244,6 +259,10 @@ private fun authDateValidation(writer: KotlinWriter) {
244259
.write("if (signingInstant < now - maxClockSkew || signingInstant > now + maxClockSkew) return null")
245260
}
246261

262+
/**
263+
* Builds a full HttpRequestBuilder object from the Ktor request,
264+
* used for SigV4 canonical request signing.
265+
*/
247266
private fun createHttpRequestBuilder(writer: KotlinWriter) {
248267
writer.write("val origin = call.request.local")
249268
.write("val payload: ByteArray = call.#T<ByteArray>()", RuntimeTypes.KtorServerRouting.requestReceive)
@@ -287,6 +306,9 @@ private fun createHttpRequestBuilder(writer: KotlinWriter) {
287306
}
288307
}
289308

309+
/**
310+
* Builds a canonical request string for SigV4A verification.
311+
*/
290312
private fun createCanonicalRequest(writer: KotlinWriter) {
291313
writer.write("val origin = call.request.local")
292314
.write("val payload: ByteArray = call.#T<ByteArray>()", RuntimeTypes.KtorServerRouting.requestReceive)
@@ -353,6 +375,9 @@ private fun createCanonicalRequest(writer: KotlinWriter) {
353375
}
354376
}
355377

378+
/**
379+
* Performs AWS SigV4 signature validation against expected HMAC.
380+
*/
356381
private fun validateSigV4(writer: KotlinWriter) {
357382
writer.withBlock("val signer = #T(", ")", RuntimeTypes.Auth.HttpAuthAws.AwsHttpSigner) {
358383
withBlock("#T.Config().apply {", "}", RuntimeTypes.Auth.HttpAuthAws.AwsHttpSigner) {
@@ -389,6 +414,9 @@ private fun validateSigV4(writer: KotlinWriter) {
389414
.write("val expectedSig = expectedAuth.substringAfter(#S).trim()", "Signature=")
390415
}
391416

417+
/**
418+
* Performs AWS SigV4A signature validation against ECDSA public key.
419+
*/
392420
private fun validateSigV4A(writer: KotlinWriter) {
393421
writer.write("val crHashHex = sha256Hex(canonicalRequest.toByteArray())")
394422
.withBlock("val stringToSign = buildString {", "}") {
@@ -405,6 +433,10 @@ private fun validateSigV4A(writer: KotlinWriter) {
405433
.write("val ok = verifier.verify(sigDer)")
406434
}
407435

436+
/**
437+
* Writes common helper functions used by SigV4 and SigV4A verification,
438+
* such as hashing, encoding, and canonical path/query building.
439+
*/
408440
private fun renderHelperFunctions(writer: KotlinWriter) {
409441
writer.withBlock("private fun sha256Hex(bytes: ByteArray): String {", "}") {
410442
write("return java.security.MessageDigest.getInstance(#S).digest(bytes).joinToString(#S) { #S.format(it) }", "SHA-256", "", "%02x")

0 commit comments

Comments
 (0)