Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for OperationContextParams #800

Merged
merged 7 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sources/ClientRuntime/Endpoints/EndpointsRequestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public class EndpointsRequestContext {
try crtContext.add(name: name, value: value)
}

public func add(name: String, value: [String]?) throws {
try crtContext.add(name: name, value: value)
}

Comment on lines +23 to +26
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Add runtime method for adding string array endpoint param to endpoint request context using CRT's new binding.

public func toCRT() -> AwsCommonRuntimeKit.EndpointsRequestContext {
crtContext
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,17 @@ fun Parameter.toSymbol(): Symbol {
}

default.ifPresent { defaultValue ->
builder.defaultValue(defaultValue.toString())
if (type.equals(ParameterType.STRING)) {
builder.defaultValue("\"$defaultValue\"")
} else if (type.equals(ParameterType.STRING_ARRAY)) {
val elementsWrappedWithEscapedQuotes = defaultValue.toString()
.removeSurrounding("[", "]")
.split(", ")
.joinToString(", ", "[", "]") { "\"$it\"" }
builder.defaultValue(elementsWrappedWithEscapedQuotes)
} else {
builder.defaultValue(defaultValue.toString())
}
Comment on lines +137 to +147
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fix default value handling for endpoint params generator.

}

return builder.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,13 @@ class JMESPathVisitor(
val writer: SwiftWriter,
Copy link
Contributor Author

@sichanyoo sichanyoo Aug 17, 2024

Choose a reason for hiding this comment

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

Changes in this file add support for wildcard flattening expression ([*]) and the keys() function of JMESPath language.

val currentExpression: JMESVariable,
val model: Model,
val symbolProvider: SymbolProvider
val symbolProvider: SymbolProvider,
val tempVars: MutableSet<String> = mutableSetOf() // Storage for variable names already used in this scope / expression.
) : ExpressionVisitor<JMESVariable> {

// A few methods are provided here for generating unique yet still somewhat
// descriptive variable names when needed.

// Storage for variable names already used in this scope / expression.
private val tempVars = mutableSetOf<String>()

// Returns a name, based on preferredName, that is guaranteed to be unique among those issued
// by this visitor.
// If not yet used, preferredName will be returned as the new variable name. If preferredName
Expand Down Expand Up @@ -154,6 +152,26 @@ class JMESPathVisitor(
}
}

private fun projection(expression: ProjectionExpression, parentVar: JMESVariable): JMESVariable {
val left = when (val left = expression.left) {
is FieldExpression -> subfield(left, parentVar)
is Subexpression -> subexpression(left, parentVar)
is ProjectionExpression -> projection(left, parentVar)
else -> left.accept(this)
}
requireNotNull(left.shape) { "projection is operating on nothing" }
return mappingBlock(expression.right, left)
}

private fun subexpression(expression: Subexpression, parentVar: JMESVariable): JMESVariable {
val left = when (val left = expression.left) {
is FieldExpression -> subfield(left, parentVar)
is Subexpression -> subexpression(left, parentVar)
else -> throw Exception("Subexpression type $left is unsupported")
}
return processRightSubexpression(expression.right, left)
}

// Performs a Boolean "and" of the left & right expressions
// A Swift compile error will result if both left & right aren't Booleans.
override fun visitAnd(expression: AndExpression): JMESVariable {
Expand Down Expand Up @@ -262,11 +280,12 @@ class JMESPathVisitor(
}
}

// Implement contains() and length() free functions which are the only 2 JMESPath methods we support.
// Implement contains(), length(), and keys() free functions which are the only 3 JMESPath methods we support.
// contains() returns true if its 1st param is a collection that contains an element equal
// to the 2nd param, false otherwise.
// length() returns the number of elements of an array, the number of key/value pairs for a map,
// or the number of characters for a string. Zero is returned if the argument is nil.
// keys() returns the keys of a map as an array of strings.
override fun visitFunction(expression: FunctionExpression): JMESVariable {
when (expression.name) {
"contains" -> {
Expand Down Expand Up @@ -322,6 +341,37 @@ class JMESPathVisitor(
else -> throw Exception("length function called on unsupported type: ${currentExpression.shape}")
}
}
"keys" -> {
if (expression.arguments.size != 1) {
throw Exception("Unexpected number of arguments to $expression")
}
val subjectExp = expression.arguments[0]
val subject = subjectExp.accept(this)

return when (subject.shape) {
is MapShape -> {
val memberShape = MemberShape.builder()
.id("smithy.swift.synthetic#KeyList\$member")
.target(stringShape)
.build()
val keyListShape = ListShape.builder()
.id("smithy.swift.synthetic#KeyList")
.member(memberShape)
.build()
val keysVar = JMESVariable("keys", false, keyListShape)
val optionalityMark = "?".takeIf { subject.isOptional } ?: ""
// example output:
// let keys = subjectExp?.keys.map { String($0) }
addTempVar(
keysVar,
"\$L\$L.keys.map { String($$0) }",
subject.name,
optionalityMark
)
}
else -> throw Exception("length function called on unsupported type: ${currentExpression.shape}")
}
}
else -> throw Exception("Unknown function type in $expression")
}
}
Expand Down Expand Up @@ -411,13 +461,16 @@ class JMESPathVisitor(
}

// Returns a subexpression derived from a parent expression.
// Only accessing fields is supported.
override fun visitSubexpression(expression: Subexpression): JMESVariable {
val leftVar = expression.left!!.accept(this)
return processRightSubexpression(expression.right, leftVar)
}

return when (val right = expression.right!!) {
is FieldExpression -> subfield(right, leftVar)
else -> throw Exception("Subexpression type $right is unsupported")
private fun processRightSubexpression(expression: JmespathExpression, parentVar: JMESVariable): JMESVariable {
return when (expression) {
is FieldExpression -> subfield(expression, parentVar)
is ProjectionExpression -> projection(expression, parentVar)
else -> throw Exception("Subexpression type $expression is unsupported")
}
}

Expand Down
Loading