-
Notifications
You must be signed in to change notification settings - Fork 18
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: bindings for EndpointsRuleEngine #79
Merged
Merged
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
1cd5291
feat: bindings for EndpointsRuleEngine
7763a05
throw ser error
5718103
add perf tests
5128aa7
fix linter
fa80602
update submodules
6bf16fc
fix linter
997e958
try to fix config read
6622d7b
try removing strict
afdbcd9
remove strict
5b12865
adapt partitions change
797577e
update submodules
2081961
update submodules
fa3b9ed
use raw string
596f345
add deinit
e83b0fa
remove AWSCommonRuntimeError
43522c1
more error fix
c96107d
use bytecursor directly
b5ebed3
deallocate
edbda57
make init internal
4ca87f8
deallocate
362df91
linter
2d695e3
add test case for prop and hdrs
18d5466
fix test case
9fd5e9b
replace JSONSerialization with custom Decoder.
a5a6191
add test cases
9846421
mixed test case
6089aad
renames
ed3118e
use old syntax
14a2a88
simplify access
9aa07ab
update subm
148cc17
fix breaking change
5df96f0
release ruleset and partitions manually
b4d7fc5
update sdkutils
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
Source/AwsCommonRuntimeKit/sdkutils/CRTAWSEndpointsRequestContext.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0. | ||
|
||
import AwsCSdkUtils | ||
|
||
/// Request context used for resolving endpoint | ||
public class CRTAWSEndpointsRequestContext { | ||
let rawValue: UnsafeMutablePointer<aws_endpoints_request_context> | ||
|
||
/// Initialize a new request context | ||
/// - Parameter allocator: Allocator to use for request context creation | ||
public init(allocator: Allocator = defaultAllocator) throws { | ||
guard let rawValue = aws_endpoints_request_context_new(allocator.rawValue) else { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
|
||
self.rawValue = rawValue | ||
} | ||
|
||
/// Add a string endpoint parameter to the request context | ||
/// - Parameters: | ||
/// - name: The name of the parameter | ||
/// - value: The value of the parameter | ||
/// - allocator: The allocator to use for the parameter | ||
public func add(name: String, value: String?, allocator: Allocator = defaultAllocator) throws { | ||
guard let value = value else { | ||
return | ||
} | ||
waahm7 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let success = aws_endpoints_request_context_add_string(allocator.rawValue, | ||
rawValue, | ||
name.awsByteCursor, | ||
value.awsByteCursor) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
} | ||
|
||
/// Add a bool endpoint parameter to the request context | ||
/// - Parameters: | ||
/// - name: The name of the parameter | ||
/// - value: The value of the parameter | ||
/// - allocator: The allocator to use for the parameter | ||
public func add(name: String, value: Bool?, allocator: Allocator = defaultAllocator) throws { | ||
guard let value = value else { | ||
return | ||
} | ||
let success = aws_endpoints_request_context_add_boolean(allocator.rawValue, rawValue, name.awsByteCursor, value) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
} | ||
|
||
deinit { | ||
aws_endpoints_request_context_release(rawValue) | ||
} | ||
} |
120 changes: 120 additions & 0 deletions
120
Source/AwsCommonRuntimeKit/sdkutils/CRTAWSEndpointsResolvedEndpoint.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0. | ||
|
||
import AwsCSdkUtils | ||
import Foundation | ||
|
||
/// Resolved endpoint | ||
public class CRTAWSEndpointResolvedEndpoint { | ||
let rawValue: OpaquePointer | ||
|
||
/// Initialize a new resolved endpoint | ||
/// - Parameter rawValue: The raw value of the resolved endpoint | ||
internal init(rawValue: OpaquePointer) { | ||
self.rawValue = rawValue | ||
|
||
aws_endpoints_resolved_endpoint_acquire(rawValue) | ||
} | ||
|
||
/// Get the type of the resolved endpoint | ||
/// - Returns: The type of the resolved endpoint | ||
public func getType() -> CRTAWSEndpointsResolvedEndpointType { | ||
let type = aws_endpoints_resolved_endpoint_get_type(rawValue) | ||
return CRTAWSEndpointsResolvedEndpointType(rawValue: type) | ||
} | ||
|
||
/// Get the URL of the resolved endpoint | ||
/// - Returns: The URL of the resolved endpoint | ||
public func getURL() throws -> String? { | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let urlOut = UnsafeMutablePointer<aws_byte_cursor>.allocate(capacity: 1) | ||
defer { | ||
urlOut.deallocate() | ||
} | ||
let success = aws_endpoints_resolved_endpoint_get_url(rawValue, urlOut) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
return urlOut.pointee.toString() | ||
} | ||
|
||
/// Get the properties of the resolved endpoint | ||
/// - Returns: The properties of the resolved endpoint | ||
public func getProperties() throws -> [String: AnyHashable]? { | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let propsOut = UnsafeMutablePointer<aws_byte_cursor>.allocate(capacity: 1) | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer { | ||
propsOut.deallocate() | ||
} | ||
let success = aws_endpoints_resolved_endpoint_get_properties(rawValue, propsOut) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
guard let data = propsOut.pointee.toString()?.data(using: .utf8) else { | ||
return nil | ||
} | ||
return try JSONDecoder().decode([String: EndpointProperty].self, from: data).toStringHashableDictionary() | ||
} | ||
|
||
/// Get the error of the resolved endpoint | ||
/// - Parameter allocator: The allocator to use for the error | ||
public func getError() throws -> String? { | ||
let errorOut = UnsafeMutablePointer<aws_byte_cursor>.allocate(capacity: 1) | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer { | ||
errorOut.deallocate() | ||
} | ||
let success = aws_endpoints_resolved_endpoint_get_error(rawValue, errorOut) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
return errorOut.pointee.toString() | ||
} | ||
|
||
/// Get headers of the resolved endpoint | ||
/// - Returns: The headers of the resolved endpoint | ||
public func getHeaders() throws -> [String: [String]]? { | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let headersOut: UnsafeMutablePointer<UnsafePointer<aws_hash_table>?> | ||
= UnsafeMutablePointer<UnsafePointer<aws_hash_table>?>.allocate(capacity: 1) | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer { | ||
headersOut.deallocate() | ||
} | ||
let success = aws_endpoints_resolved_endpoint_get_headers(rawValue, headersOut) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
|
||
var headers: [String: [String]] = [:] | ||
var iter = aws_hash_iter_begin(headersOut.pointee) | ||
|
||
while !aws_hash_iter_done(&iter) { | ||
// Get the key | ||
let keyPtr = iter.element.key.bindMemory(to: aws_string.self, capacity: 1) | ||
guard let key = String(awsString: keyPtr) else { | ||
throw CRTError.stringConversionError(keyPtr) | ||
} | ||
|
||
// Get the value | ||
let arrayPtr = iter.element.value.bindMemory(to: aws_array_list.self, capacity: 1) | ||
var array: [String] = [] | ||
for index in 0..<aws_array_list_length(arrayPtr) { | ||
var valPtr: UnsafeMutableRawPointer! = nil | ||
defer { | ||
valPtr?.deallocate() | ||
} | ||
aws_array_list_get_at(arrayPtr, &valPtr, index) | ||
let strPtr = valPtr.bindMemory(to: aws_string.self, capacity: 1) | ||
guard let val = String(awsString: strPtr) else { | ||
throw CRTError.stringConversionError(strPtr) | ||
} | ||
array.append(val) | ||
} | ||
|
||
headers[key] = array | ||
aws_hash_iter_next(&iter) | ||
} | ||
|
||
return headers | ||
} | ||
|
||
deinit { | ||
aws_endpoints_resolved_endpoint_release(rawValue) | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
Source/AwsCommonRuntimeKit/sdkutils/CRTAWSEndpointsResolvedEndpointType.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0. | ||
|
||
import AwsCSdkUtils | ||
|
||
/// Resolved endpoint type | ||
public enum CRTAWSEndpointsResolvedEndpointType { | ||
/// Used for endpoints that are resolved successfully | ||
case endpoint | ||
/// Used for endpoints that resolve to an error | ||
case error | ||
} | ||
|
||
extension CRTAWSEndpointsResolvedEndpointType: RawRepresentable, CaseIterable { | ||
public init(rawValue: aws_endpoints_resolved_endpoint_type) { | ||
let value = Self.allCases.first(where: {$0.rawValue == rawValue}) | ||
self = value ?? .endpoint | ||
} | ||
|
||
public var rawValue: aws_endpoints_resolved_endpoint_type { | ||
switch self { | ||
case .endpoint: | ||
return AWS_ENDPOINTS_RESOLVED_ENDPOINT | ||
case .error: | ||
return AWS_ENDPOINTS_RESOLVED_ERROR | ||
} | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
Source/AwsCommonRuntimeKit/sdkutils/CRTAWSEndpointsRuleEngine.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0. | ||
|
||
import AwsCSdkUtils | ||
|
||
/// Rule engine for matching endpoint rules | ||
public class CRTAWSEndpointsRuleEngine { | ||
let partitions: UnsafeMutablePointer<aws_partitions_config> | ||
let ruleSet: UnsafeMutablePointer<aws_endpoints_ruleset> | ||
let rawValue: OpaquePointer | ||
|
||
/// Initialize a new rule engine | ||
/// - Parameters: | ||
/// - partitions: JSON string containing partition data | ||
/// - ruleSet: The rule set string to use for the rule engine | ||
/// - allocator: The allocator to use for creating rule engine | ||
public init(partitions: String, ruleSet: String, allocator: Allocator = defaultAllocator) throws { | ||
guard let partitions = aws_partitions_config_new_from_string(allocator.rawValue, partitions.newByteCursor().rawValue), | ||
let ruleSet = aws_endpoints_ruleset_new_from_string(allocator.rawValue, ruleSet.newByteCursor().rawValue), | ||
let rawValue = aws_endpoints_rule_engine_new(allocator.rawValue, ruleSet, partitions) else { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
|
||
self.partitions = partitions | ||
self.ruleSet = ruleSet | ||
self.rawValue = rawValue | ||
} | ||
|
||
/// Resolve an endpoint from the rule engine using the provided request context | ||
/// - Parameter context: The request context to use for endpoint resolution | ||
/// - Returns: The resolved endpoint | ||
public func resolve(context: CRTAWSEndpointsRequestContext) throws -> CRTAWSEndpointResolvedEndpoint? { | ||
let resolvedEndpoint: UnsafeMutablePointer<OpaquePointer?>? = UnsafeMutablePointer.allocate(capacity: 1) | ||
ganeshnj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer { | ||
resolvedEndpoint?.deallocate() | ||
} | ||
let success = aws_endpoints_rule_engine_resolve(rawValue, context.rawValue, resolvedEndpoint) | ||
if success != 0 { | ||
throw CRTError.crtError(AWSError.makeFromLastError()) | ||
} | ||
|
||
guard let pointee = resolvedEndpoint?.pointee else { | ||
return nil | ||
} | ||
|
||
return CRTAWSEndpointResolvedEndpoint(rawValue: pointee) | ||
} | ||
|
||
deinit { | ||
aws_partitions_config_release(partitions) | ||
aws_endpoints_rule_engine_release(rawValue) | ||
aws_endpoints_ruleset_release(ruleSet) | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
Source/AwsCommonRuntimeKit/sdkutils/EndpointProperty.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0. | ||
|
||
/// Struct that represents endpoint property which can be a boolean, string or array of endpoint properties | ||
internal enum EndpointProperty { | ||
case bool(Bool) | ||
case string(String) | ||
indirect case array([EndpointProperty]) | ||
indirect case dictionary([String: EndpointProperty]) | ||
|
||
func toAnyHashable() -> AnyHashable { | ||
switch self { | ||
case .bool(let value): | ||
return AnyHashable(value) | ||
case .string(let value): | ||
return AnyHashable(value) | ||
case .array(let value): | ||
return AnyHashable(value.map { $0.toAnyHashable() }) | ||
case .dictionary(let value): | ||
return AnyHashable(value.mapValues { $0.toAnyHashable() }) | ||
} | ||
} | ||
} | ||
|
||
/// Decodable conformance | ||
extension EndpointProperty: Decodable { | ||
init(from decoder: Decoder) throws { | ||
if let container = try? decoder.container(keyedBy: EndpointPropertyCodingKeys.self) { | ||
self = EndpointProperty(from: container) | ||
} else if let container = try? decoder.unkeyedContainer() { | ||
self = EndpointProperty(from: container) | ||
} else if let container = try? decoder.singleValueContainer() { | ||
self = EndpointProperty(from: container) | ||
} else { | ||
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "")) | ||
} | ||
} | ||
|
||
init(from container: KeyedDecodingContainer<EndpointPropertyCodingKeys>) { | ||
var dict: [String: EndpointProperty] = [:] | ||
for key in container.allKeys { | ||
if let value = try? container.decode(Bool.self, forKey: key) { | ||
dict[key.stringValue] = .bool(value) | ||
} else if let value = try? container.decode(String.self, forKey: key) { | ||
dict[key.stringValue] = .string(value) | ||
} else if let value = try? container.nestedContainer(keyedBy: EndpointPropertyCodingKeys.self, forKey: key) { | ||
dict[key.stringValue] = EndpointProperty(from: value) | ||
} else if let value = try? container.nestedUnkeyedContainer(forKey: key) { | ||
dict[key.stringValue] = EndpointProperty(from: value) | ||
} | ||
} | ||
self = .dictionary(dict) | ||
} | ||
|
||
init(from container: UnkeyedDecodingContainer) { | ||
var container = container | ||
var arr: [EndpointProperty] = [] | ||
while !container.isAtEnd { | ||
if let value = try? container.decode(Bool.self) { | ||
arr.append(.bool(value)) | ||
} else if let value = try? container.decode(String.self) { | ||
arr.append(.string(value)) | ||
} else if let value = try? container.nestedContainer(keyedBy: EndpointPropertyCodingKeys.self) { | ||
arr.append(EndpointProperty(from: value)) | ||
} else if let value = try? container.nestedUnkeyedContainer() { | ||
arr.append(EndpointProperty(from: value)) | ||
} | ||
} | ||
self = .array(arr) | ||
} | ||
|
||
init(from container: SingleValueDecodingContainer) { | ||
if let value = try? container.decode(Bool.self) { | ||
self = .bool(value) | ||
} else if let value = try? container.decode(String.self) { | ||
self = .string(value) | ||
} else { | ||
assertionFailure("Invalid EndpointProperty") | ||
self = .string("") | ||
} | ||
} | ||
} | ||
|
||
extension Dictionary where Key == String, Value == EndpointProperty { | ||
/// Converts EndpointProperty to a dictionary of `String`: `AnyHashable` | ||
/// - Returns: Dictionary of `String`: `AnyHashable` | ||
func toStringHashableDictionary() -> [String: AnyHashable] { | ||
var dict: [String: AnyHashable] = [:] | ||
for (key, value) in self { | ||
dict[key] = value.toAnyHashable() | ||
} | ||
return dict | ||
} | ||
} | ||
|
||
/// Coding keys for `EndpointProperty` | ||
internal struct EndpointPropertyCodingKeys: CodingKey { | ||
var stringValue: String | ||
|
||
init?(stringValue: String) { | ||
self.stringValue = stringValue | ||
} | ||
|
||
var intValue: Int? | ||
|
||
init?(intValue: Int) { | ||
self.init(stringValue: "\(intValue)") | ||
self.intValue = intValue | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strict is ignoring the
.swiftlint
config file and redundant to the line 20 after removing strict.