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
6 changes: 3 additions & 3 deletions Example/AblyChatExample/Mocks/Misc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ final class MockMessagesPaginatedResult: PaginatedResult {

var isLast: Bool { fatalError("Not implemented") }

var next: Self? { fatalError("Not implemented") }
func next() async throws(ARTErrorInfo) -> Self? { fatalError("Not implemented") }

var first: Self { fatalError("Not implemented") }
func first() async throws(ARTErrorInfo) -> Self { fatalError("Not implemented") }

var current: Self { fatalError("Not implemented") }
func current() async throws(ARTErrorInfo) -> Self { fatalError("Not implemented") }

init(clientID: String, roomName: String, numberOfMockMessages: Int = 3) {
self.clientID = clientID
Expand Down
49 changes: 22 additions & 27 deletions Sources/AblyChat/PaginatedResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ public protocol PaginatedResult<Item>: AnyObject, Sendable {
var hasNext: Bool { get }
// swiftlint:disable:next missing_docs
var isLast: Bool { get }
// Note that there seems to be a compiler bug (https://github.com/swiftlang/swift/issues/79992) that means that the compiler does not enforce the access level of the error type for property getters. I accidentally originally wrote these as throws(InternalError), which the compiler should have rejected since InternalError is internal and this protocol is public, but it did not reject it and this mistake was only noticed in code review.
// swiftlint:disable:next missing_docs
var next: Self? { get async throws(ARTErrorInfo) }
func next() async throws(ARTErrorInfo) -> Self?
// swiftlint:disable:next missing_docs
var first: Self { get async throws(ARTErrorInfo) }
func first() async throws(ARTErrorInfo) -> Self
// swiftlint:disable:next missing_docs
var current: Self { get async throws(ARTErrorInfo) }
func current() async throws(ARTErrorInfo) -> Self
}

/// Used internally to reduce the amount of duplicate code when interacting with `ARTHTTPPaginatedCallback`'s. The wrapper takes in the callback result from the caller e.g. `realtime.request` and either throws the appropriate error, or decodes and returns the response.
Expand Down Expand Up @@ -75,37 +74,33 @@ internal final class PaginatedResultWrapper<Item: JSONDecodable & Sendable & Equ
}

/// Asynchronously fetch the next page if available
internal var next: PaginatedResultWrapper<Item>? {
get async throws(ARTErrorInfo) {
do {
return try await withCheckedContinuation { continuation in
paginatedResponse.next { paginatedResponse, error in
ARTHTTPPaginatedCallbackWrapper(callbackResult: (paginatedResponse, error)).handleResponse(continuation: continuation)
}
}.get()
} catch {
throw error.toARTErrorInfo()
}
internal func next() async throws(ARTErrorInfo) -> PaginatedResultWrapper<Item>? {
do {
return try await withCheckedContinuation { continuation in
paginatedResponse.next { paginatedResponse, error in
ARTHTTPPaginatedCallbackWrapper(callbackResult: (paginatedResponse, error)).handleResponse(continuation: continuation)
}
}.get()
} catch {
throw error.toARTErrorInfo()
}
}

/// Asynchronously fetch the first page
internal var first: PaginatedResultWrapper<Item> {
get async throws(ARTErrorInfo) {
do {
return try await withCheckedContinuation { continuation in
paginatedResponse.first { paginatedResponse, error in
ARTHTTPPaginatedCallbackWrapper(callbackResult: (paginatedResponse, error)).handleResponse(continuation: continuation)
}
}.get()
} catch {
throw error.toARTErrorInfo()
}
internal func first() async throws(ARTErrorInfo) -> PaginatedResultWrapper<Item> {
do {
return try await withCheckedContinuation { continuation in
paginatedResponse.first { paginatedResponse, error in
ARTHTTPPaginatedCallbackWrapper(callbackResult: (paginatedResponse, error)).handleResponse(continuation: continuation)
}
}.get()
} catch {
throw error.toARTErrorInfo()
}
}

/// Asynchronously fetch the current page
internal var current: PaginatedResultWrapper<Item> {
internal func current() async throws(ARTErrorInfo) -> PaginatedResultWrapper<Item> {
self
}

Expand Down
4 changes: 2 additions & 2 deletions Tests/AblyChatTests/DefaultMessagesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ struct DefaultMessagesTests {
#expect(paginatedResult.hasNext == true)

// CHA-M5h: which can be further inspected to paginate across results
let nextPage = try #require(await paginatedResult.next)
let nextPage = try #require(await paginatedResult.next())
#expect(nextPage.hasNext == false)
}

Expand Down Expand Up @@ -519,7 +519,7 @@ struct DefaultMessagesTests {

// Then
// CHA-M6a: which can then be paginated through
let nextPage = try #require(await paginatedResult.next)
let nextPage = try #require(await paginatedResult.next())
#expect(nextPage.hasNext == false)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Ably
@testable import AblyChat
import AsyncAlgorithms
import Foundation
Expand All @@ -10,11 +11,11 @@ private final class MockPaginatedResult<Item: Equatable>: PaginatedResult, @Main

var isLast: Bool { fatalError("Not implemented") }

var next: MockPaginatedResult<Item>? { fatalError("Not implemented") }
func next() async throws(ARTErrorInfo) -> MockPaginatedResult<Item>? { fatalError("Not implemented") }

var first: MockPaginatedResult<Item> { fatalError("Not implemented") }
func first() async throws(ARTErrorInfo) -> MockPaginatedResult<Item> { fatalError("Not implemented") }

var current: MockPaginatedResult<Item> { fatalError("Not implemented") }
func current() async throws(ARTErrorInfo) -> MockPaginatedResult<Item> { fatalError("Not implemented") }

init() {}

Expand Down