Skip to content

Commit

Permalink
Add option to allow ContextKey overwrite on unsafeAdd (#5)
Browse files Browse the repository at this point in the history
* Add option to allow ContextKey overwrite on `unsafeAdd`

* Swiftlint
  • Loading branch information
Supereg authored Feb 6, 2022
1 parent 30b8886 commit 94f5bef
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Sources/ApodiniContext/CodableContextKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ private let encoder = JSONEncoder()
private let decoder = JSONDecoder()

extension CodableContextKey {
/// Default identifier is derived from the swift type name
public static var identifier: String {
"\(Self.self)"
}

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

/// Default implementation for decode from base64 string.
public static func decode(from base64String: String) throws -> Value {
guard let data = Data(base64Encoded: base64String) else {
fatalError("Failed to unwrap bas64 encoded data string: \(base64String)")
Expand Down
6 changes: 4 additions & 2 deletions Sources/ApodiniContext/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ public struct Context: ContextKeyRetrievable {
/// - Parameters:
/// - contextKey: The context to add value for.
/// - value: The value to add.
public func unsafeAdd<C: OptionalContextKey>(_ contextKey: C.Type = C.self, value: C.Value) {
/// - allowOverwrite: This Bool controls if the unsafe addition should allow overwriting an existing entry.
/// Use this option with caution! This method does NOT reduce multiple values for the same key. It OVERWRITES!
public func unsafeAdd<C: OptionalContextKey>(_ contextKey: C.Type = C.self, value: C.Value, allowOverwrite: Bool = false) {
let key = ObjectIdentifier(contextKey)

precondition(entries[key] == nil, "Cannot overwrite existing ContextKey entry with `unsafeAdd`: \(C.self): \(value)")
precondition(entries[key] == nil || allowOverwrite, "Cannot overwrite existing ContextKey entry with `unsafeAdd`: \(C.self): \(value)")
if let codableContextKey = contextKey as? AnyCodableContextKey.Type {
// we need to prevent this. as Otherwise we would need to handle merging this stuff which get really complex
precondition(decodedEntries[codableContextKey.identifier] == nil, "Cannot overwrite existing CodableContextKey entry with `unsafeAdd`: \(C.self): \(value)")
Expand Down
18 changes: 17 additions & 1 deletion Tests/ApodiniContextTests/ContextKeyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,27 @@ class ContextKeyTests: XCTestCase {
let decoder = FineJSONDecoder()

let encodedContext = try encoder.encode(context)
XCTAssertEqual(String(data: encodedContext, encoding: .utf8), "{\"CodableArrayStringContextKey\":\"WyJIZWxsbyBTdW4iXQ==\",\"CodableStringContextKey\":\"IkhlbGxvIFdvcmxkIg==\"}")
XCTAssertEqual(
String(data: encodedContext, encoding: .utf8),
"{\"CodableArrayStringContextKey\":\"WyJIZWxsbyBTdW4iXQ==\",\"CodableStringContextKey\":\"IkhlbGxvIFdvcmxkIg==\"}"
)
let decodedContext = try decoder.decode(Context.self, from: encodedContext)

XCTAssertEqual(decodedContext.get(valueFor: CodableStringContextKey.self), "Hello World")
XCTAssertEqual(decodedContext.get(valueFor: RequiredCodableStringContextKey.self), "Default Value!")
XCTAssertEqual(decodedContext.get(valueFor: CodableArrayStringContextKey.self), ["Hello Sun"])
}

func testUnsafeAddAllowingOverwrite() {
struct CodableStringContextKey: CodableContextKey {
typealias Value = String
}

let context = Context()

context.unsafeAdd(CodableStringContextKey.self, value: "Hello World")
XCTAssertEqual(context.get(valueFor: CodableStringContextKey.self), "Hello World")
context.unsafeAdd(CodableStringContextKey.self, value: "Hello Mars", allowOverwrite: true)
XCTAssertEqual(context.get(valueFor: CodableStringContextKey.self), "Hello Mars")
}
}

0 comments on commit 94f5bef

Please sign in to comment.