Skip to content
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
12 changes: 12 additions & 0 deletions Sources/Sharing/SharedKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ extension Shared {
self.init(wrappedValue: wrappedValue(), key.base)
}

/// Replaces a shared reference's key with a shared key that provides a default value and
/// attempts to load its value.
public func load<K: SharedKey<Value>>(_ key: K.Default) async throws {
try await load(key.base)
}

/// Replaces a shared reference's key and attempts to load its value.
///
/// - Parameter key: A shared key associated with the shared reference. It is responsible for
Expand All @@ -100,6 +106,12 @@ extension Shared {
try await load()
}

/// Creates a shared reference from a shared key that provides a default value by loading it
/// from its external source.
public init<K: SharedKey<Value>>(require key: K.Default) async throws {
try await self.init(require: key.base)
}

/// Creates a shared reference to a value using a shared key by loading it from its external
/// source.
///
Expand Down
12 changes: 12 additions & 0 deletions Sources/Sharing/SharedReaderKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ extension SharedReader {
self.init(wrappedValue: wrappedValue(), key.base)
}

/// Replaces a shared reference's key with a shared key that provides a default value and
/// attempts to load its value.
public func load<K: SharedReaderKey<Value>>(_ key: K.Default) async throws {
try await load(key.base)
}

/// Replaces a shared reference's key and attempts to load its value.
///
/// - Parameter key: A shared key associated with the shared reference. It is responsible for
Expand All @@ -173,6 +179,12 @@ extension SharedReader {
try await load(key)
}

/// Creates a shared reference from a shared key that provides a default value by loading it from
/// its external source.
public init<K: SharedReaderKey<Value>>(require key: K.Default) async throws {
try await self.init(require: key.base)
}

/// Creates a shared reference to a read-only value using a shared key by loading it from its
/// external source.
///
Expand Down
80 changes: 80 additions & 0 deletions Tests/SharingTests/DefaultTests.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ConcurrencyExtras
import Sharing
import Testing

Expand Down Expand Up @@ -149,6 +150,85 @@ import Testing
#expect(count == 3)
#expect(countReader == 3)
}

@Test func loadDefaultKeyUsesBaseReference() async throws {
let subscriptionCount = LockIsolated(0)
let key = SubscriptionCountingKey(
id: "loadDefaultKeyUsesBaseReference",
subscriptionCount: subscriptionCount
)
let defaultKey = SubscriptionCountingKey.Default[key, default: 0]

@SharedReader(value: 0) var value
try await $value.load(defaultKey)
@SharedReader(defaultKey) var otherValue

#expect(subscriptionCount.value == 1)
}

@Test func requireDefaultKeyUsesBaseReference() async throws {
let subscriptionCount = LockIsolated(0)
let key = SubscriptionCountingKey(
id: "requireDefaultKeyUsesBaseReference",
subscriptionCount: subscriptionCount
)
let defaultKey = SubscriptionCountingKey.Default[key, default: 0]

let value = try await SharedReader(require: defaultKey)
@SharedReader(defaultKey) var otherValue

#expect(subscriptionCount.value == 1)
}

@Test func sharedLoadDefaultKeyUsesBaseReference() async throws {
let subscriptionCount = LockIsolated(0)
let key = SubscriptionCountingKey(
id: "sharedLoadDefaultKeyUsesBaseReference",
subscriptionCount: subscriptionCount
)
let defaultKey = SubscriptionCountingKey.Default[key, default: 0]

@Shared(value: 0) var value
try await $value.load(defaultKey)
@Shared(defaultKey) var otherValue

#expect(subscriptionCount.value == 1)
}

@Test func sharedRequireDefaultKeyUsesBaseReference() async throws {
let subscriptionCount = LockIsolated(0)
let key = SubscriptionCountingKey(
id: "sharedRequireDefaultKeyUsesBaseReference",
subscriptionCount: subscriptionCount
)
let defaultKey = SubscriptionCountingKey.Default[key, default: 0]

let value = try await Shared(require: defaultKey)
@Shared(defaultKey) var otherValue

#expect(subscriptionCount.value == 1)
}
}
}

private struct SubscriptionCountingKey: SharedKey {
let id: String
let subscriptionCount: LockIsolated<Int>

func load(context: LoadContext<Int>, continuation: LoadContinuation<Int>) {
continuation.resume(returning: 0)
}

func subscribe(
context: LoadContext<Int>,
subscriber: SharedSubscriber<Int>
) -> SharedSubscription {
subscriptionCount.withValue { $0 += 1 }
return SharedSubscription {}
}

func save(_ value: Int, context: SaveContext, continuation: SaveContinuation) {
continuation.resume()
}
}

Expand Down
Loading