Skip to content

Commit 94f5bef

Browse files
Add option to allow ContextKey overwrite on unsafeAdd (#5)
* Add option to allow ContextKey overwrite on `unsafeAdd` * Swiftlint
1 parent 30b8886 commit 94f5bef

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

Sources/ApodiniContext/CodableContextKey.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ private let encoder = JSONEncoder()
2424
private let decoder = JSONDecoder()
2525

2626
extension CodableContextKey {
27+
/// Default identifier is derived from the swift type name
2728
public static var identifier: String {
2829
"\(Self.self)"
2930
}
3031

32+
/// Default implementation for anyEncode to base64 string.
3133
public static func anyEncode(value: Any) throws -> String {
3234
guard let value = value as? Self.Value else {
3335
fatalError("CodableContextKey.anyEncode(value:) received illegal value type \(type(of: value)) instead of \(Value.self)")
@@ -38,6 +40,7 @@ extension CodableContextKey {
3840
.base64EncodedString()
3941
}
4042

43+
/// Default implementation for decode from base64 string.
4144
public static func decode(from base64String: String) throws -> Value {
4245
guard let data = Data(base64Encoded: base64String) else {
4346
fatalError("Failed to unwrap bas64 encoded data string: \(base64String)")

Sources/ApodiniContext/Context.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ public struct Context: ContextKeyRetrievable {
8989
/// - Parameters:
9090
/// - contextKey: The context to add value for.
9191
/// - value: The value to add.
92-
public func unsafeAdd<C: OptionalContextKey>(_ contextKey: C.Type = C.self, value: C.Value) {
92+
/// - allowOverwrite: This Bool controls if the unsafe addition should allow overwriting an existing entry.
93+
/// Use this option with caution! This method does NOT reduce multiple values for the same key. It OVERWRITES!
94+
public func unsafeAdd<C: OptionalContextKey>(_ contextKey: C.Type = C.self, value: C.Value, allowOverwrite: Bool = false) {
9395
let key = ObjectIdentifier(contextKey)
9496

95-
precondition(entries[key] == nil, "Cannot overwrite existing ContextKey entry with `unsafeAdd`: \(C.self): \(value)")
97+
precondition(entries[key] == nil || allowOverwrite, "Cannot overwrite existing ContextKey entry with `unsafeAdd`: \(C.self): \(value)")
9698
if let codableContextKey = contextKey as? AnyCodableContextKey.Type {
9799
// we need to prevent this. as Otherwise we would need to handle merging this stuff which get really complex
98100
precondition(decodedEntries[codableContextKey.identifier] == nil, "Cannot overwrite existing CodableContextKey entry with `unsafeAdd`: \(C.self): \(value)")

Tests/ApodiniContextTests/ContextKeyTests.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,27 @@ class ContextKeyTests: XCTestCase {
107107
let decoder = FineJSONDecoder()
108108

109109
let encodedContext = try encoder.encode(context)
110-
XCTAssertEqual(String(data: encodedContext, encoding: .utf8), "{\"CodableArrayStringContextKey\":\"WyJIZWxsbyBTdW4iXQ==\",\"CodableStringContextKey\":\"IkhlbGxvIFdvcmxkIg==\"}")
110+
XCTAssertEqual(
111+
String(data: encodedContext, encoding: .utf8),
112+
"{\"CodableArrayStringContextKey\":\"WyJIZWxsbyBTdW4iXQ==\",\"CodableStringContextKey\":\"IkhlbGxvIFdvcmxkIg==\"}"
113+
)
111114
let decodedContext = try decoder.decode(Context.self, from: encodedContext)
112115

113116
XCTAssertEqual(decodedContext.get(valueFor: CodableStringContextKey.self), "Hello World")
114117
XCTAssertEqual(decodedContext.get(valueFor: RequiredCodableStringContextKey.self), "Default Value!")
115118
XCTAssertEqual(decodedContext.get(valueFor: CodableArrayStringContextKey.self), ["Hello Sun"])
116119
}
120+
121+
func testUnsafeAddAllowingOverwrite() {
122+
struct CodableStringContextKey: CodableContextKey {
123+
typealias Value = String
124+
}
125+
126+
let context = Context()
127+
128+
context.unsafeAdd(CodableStringContextKey.self, value: "Hello World")
129+
XCTAssertEqual(context.get(valueFor: CodableStringContextKey.self), "Hello World")
130+
context.unsafeAdd(CodableStringContextKey.self, value: "Hello Mars", allowOverwrite: true)
131+
XCTAssertEqual(context.get(valueFor: CodableStringContextKey.self), "Hello Mars")
132+
}
117133
}

0 commit comments

Comments
 (0)