Skip to content

Commit

Permalink
Merge development into main
Browse files Browse the repository at this point in the history
  • Loading branch information
sbertix committed Apr 10, 2021
2 parents 434947b + 7f5231c commit 84ddaa5
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 1 deletion.
85 changes: 85 additions & 0 deletions Sources/ComposableStorage/Concrete/AnyStorage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// AnyStorage.swift
// ComposableRequest
//
// Created by Stefano Bertagno on 10/04/21.
//

import Foundation

/// A `struct` defining a type-erased `Storage`.
public struct AnyStorage<Item: Storable>: Storage {
/// Retreive a single item.
private let retreiver: (String) throws -> Item?
/// Retreieve all items.
private let exhauster: () throws -> [Item]
/// Store a single item.
private let persister: (Item) throws -> Item
/// Discard a single item.
private let remover: (String) throws -> Item?
/// Wipe the entire storage.
private let wiper: () throws -> Void

/// Init.
///
/// - parameter storage: A valid `Storage`.
public init<S: Storage>(_ storage: S) where S.Item == Item {
self.retreiver = { try S.item(matching: $0, in: storage) }
self.exhauster = { try S.items(in: storage) }
self.persister = { try S.store($0, in: storage) }
self.remover = { try S.discard($0, in: storage) }
self.wiper = { try S.empty(storage) }
}

/// Return the first `Item` matching `label`, `nil` if none was found.
///
/// - parameters:
/// - label: A valid `String`.
/// - storage: A valid `Storage`.
/// - returns: An optional `Item`.
/// - throws: Some `Error`.
public static func item(matching label: String, in storage: Self) throws -> Item? {
try storage.retreiver(label)
}

/// Return all stored `Item`s.
///
/// - parameter storage: A valid `Storage`.
/// - returns: An order collection of `Item`s.
/// - throws: Some `Error`.
public static func items(in storage: Self) throws -> [Item] {
try storage.exhauster()
}

/// Store some `Item`, overwriting the ones matching its `label`.
///
/// - parameters:
/// - item: A valid `Item`.
/// - storage: A valid `Storage`.
/// - returns: `item`.
/// - throws: Some `Error`.
@discardableResult
public static func store(_ item: Item, in storage: Self) throws -> Item {
try storage.persister(item)
}

/// Return an `Item`, if found, then removes it from storage.
///
/// - parameters:
/// - label: A valid `String`.
/// - storage: A valid `Storage`.
/// - returns: An optional `Item`.
/// - throws: Some `Error`.
@discardableResult
public static func discard(_ label: String, in storage: Self) throws -> Item? {
try storage.remover(label)
}

/// Empty storage.
///
/// - parameter storage: A valid `Storage`.
/// - throws: Some `Error`.
public static func empty(_ storage: Self) throws {
try storage.wiper()
}
}
10 changes: 9 additions & 1 deletion Sources/ComposableStorageCrypto/KeychainStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@

import Foundation

@_exported import ComposableStorage
import Swiftchain
import protocol ComposableStorage.Storable
import protocol ComposableStorage.ThrowingStorage

/// A `typealias` for `Swiftchain.Keychain`.
///
/// - note:
/// We prefer this to `import @_exported`, as we can't guarantee `@_exported`
/// to stick with future versions of **Swift**.
public typealias Keychain = Swiftchain.Keychain

/// A `struct` defining a `Storage` caching `Item`s **safely** inside the user's **Keychain**.
public struct KeychainStorage<Item: Storable>: ThrowingStorage {
Expand Down
2 changes: 2 additions & 0 deletions Tests/ComposableRequestTests/StorageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ final class StorageTests: XCTestCase {
let storage = KeychainStorage<Item>()
try process(storage)
try process(storage: storage)
try process(storage: AnyStorage(storage))
}

/// Test `TransientStorage`.
Expand All @@ -134,5 +135,6 @@ final class StorageTests: XCTestCase {
let storage = UserDefaultsStorage<Item>()
process(storage)
try process(storage: storage)
try process(storage: AnyStorage(storage))
}
}

0 comments on commit 84ddaa5

Please sign in to comment.