init
This commit is contained in:
commit
e4dbd93c3c
|
@ -0,0 +1,22 @@
|
|||
# This workflow will build a Swift project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build
|
||||
run: swift build -v
|
||||
- name: Run tests
|
||||
run: swift test -v
|
|
@ -0,0 +1,37 @@
|
|||
name: docc
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
pages:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: docbuild
|
||||
run: |
|
||||
xcodebuild docbuild -scheme Cache \
|
||||
-derivedDataPath /tmp/docbuild \
|
||||
-destination 'generic/platform=iOS';
|
||||
$(xcrun --find docc) process-archive \
|
||||
transform-for-static-hosting /tmp/docbuild/Build/Products/Debug-iphoneos/Cache.doccarchive \
|
||||
--hosting-base-path Cache \
|
||||
--output-path docs;
|
||||
echo "<script>window.location.href += \"/documentation/cache\"</script>" > docs/index.html;
|
||||
- name: artifacts
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: 'docs'
|
||||
- name: deploy
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
|
@ -0,0 +1,9 @@
|
|||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/config/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "c",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/0xOpenBytes/c",
|
||||
"state" : {
|
||||
"revision" : "876899c63377f407a27316ce24eb7bc37653cb13",
|
||||
"version" : "4.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "t",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/0xOpenBytes/t",
|
||||
"state" : {
|
||||
"revision" : "c111675ac4d84af23d2d9b65bffaf1829c376986",
|
||||
"version" : "1.0.4"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// swift-tools-version: 5.7
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Cache",
|
||||
platforms: [
|
||||
.iOS(.v14),
|
||||
.macOS(.v11),
|
||||
.watchOS(.v7),
|
||||
.tvOS(.v14)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "Cache",
|
||||
targets: ["Cache"]
|
||||
)
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
.package(url: "https://github.com/0xOpenBytes/c", from: "4.0.0")
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
name: "Cache",
|
||||
dependencies: ["c"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "CacheTests",
|
||||
dependencies: ["Cache"]
|
||||
)
|
||||
]
|
||||
)
|
|
@ -0,0 +1,26 @@
|
|||
# Cache
|
||||
|
||||
Cache is a simple in-memory key-value store that provides thread-safe access to its contents. It is used for storing frequently used data that takes time or resources to compute. When a value is added to the cache, it is stored in memory and can be retrieved quickly on subsequent accesses.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the Cache, first create an instance with the desired key and value types. You can then use the set(_:forKey:) method to add items to the cache, and the get(_:) method to retrieve items from the cache.
|
||||
|
||||
```swift
|
||||
let cache = Cache<String, Int>()
|
||||
cache.set(42, forKey: "answer")
|
||||
let answer = cache.get("answer") // answer == 42
|
||||
```
|
||||
|
||||
The Cache also supports removal of items from the cache using the remove(_:) method. To remove all items from the cache, use the clear() method.
|
||||
|
||||
```swift
|
||||
let cache = Cache<String, Int>()
|
||||
cache.set(42, forKey: "answer")
|
||||
cache.remove("answer")
|
||||
let answer = cache.get("answer") // answer == nil
|
||||
```
|
||||
|
||||
### Thread Safety
|
||||
|
||||
The Cache is designed to be thread-safe, allowing multiple threads to access and modify the cache without the risk of data races.
|
|
@ -0,0 +1,14 @@
|
|||
import c
|
||||
|
||||
/**
|
||||
A convenience subclass of `c.Cache`.
|
||||
|
||||
To use the cache, create an instance of `Cache` with the desired key and value types. You can then use the `set(_:forKey:)` method to add items to the cache, and the `get(_:)` or `resolve(_:)` method to retrieve items from the cache.
|
||||
|
||||
```swift
|
||||
let cache = Cache<String, Int>()
|
||||
cache.set(42, forKey: "answer")
|
||||
let answer = cache.get("answer") // answer == 42
|
||||
```
|
||||
*/
|
||||
open class Cache<Key: Hashable, Value>: c.Cache<Key, Value> { }
|
|
@ -0,0 +1,19 @@
|
|||
import c
|
||||
|
||||
/**
|
||||
`JSON` is a generic struct that provides a convenient way to parse and manipulate JSON data. It uses the `c` library to parse and serialize JSON data.
|
||||
|
||||
To create a `JSON` object, pass a `Data` object that contains JSON data to the `init(data:)` method. You can then use the `get(_:)` or `resolve(_:)` method to extract individual values from the JSON data.
|
||||
|
||||
let jsonData = "{\"name\": \"John Doe\", \"age\": 42}".data(using: .utf8)!
|
||||
let json = JSON<MockJSONKey>(data: jsonData)
|
||||
|
||||
let name: String = try json.resolve(.name)
|
||||
let age: Int = try json.resolve(.age)
|
||||
|
||||
You can also use the `set(value:forKey:)` method to update the values in the JSON object, and the `get(_:)` or `resolve(_:)` method to retrieve the values from the object.
|
||||
|
||||
json.set(value: "Jane Doe", forKey: .name)
|
||||
let newName: String = try json.resolve(.name)
|
||||
*/
|
||||
public typealias JSON = c.JSON
|
|
@ -0,0 +1,93 @@
|
|||
import SwiftUI
|
||||
import XCTest
|
||||
@testable import Cache
|
||||
|
||||
final class CacheTests: XCTestCase {
|
||||
func testCacheString() throws {
|
||||
enum CacheKey {
|
||||
case text
|
||||
}
|
||||
|
||||
let cache: Cache<CacheKey, String> = Cache(
|
||||
initialValues: [
|
||||
.text: "Hello, World!"
|
||||
]
|
||||
)
|
||||
|
||||
let cachedValue: String = try XCTUnwrap(cache.get(.text))
|
||||
|
||||
XCTAssertEqual(cachedValue, "Hello, World!")
|
||||
}
|
||||
|
||||
func testCacheImage() throws {
|
||||
let cache: Cache<URL, Image> = Cache()
|
||||
|
||||
let imageURL = try XCTUnwrap(URL(string: "test-image"))
|
||||
|
||||
XCTAssertNil(cache.get(imageURL))
|
||||
|
||||
cache.set(value: Image(systemName: "circle"), forKey: imageURL)
|
||||
|
||||
XCTAssertNotNil(cache.get(imageURL))
|
||||
|
||||
cache.remove(imageURL)
|
||||
|
||||
XCTAssertNil(cache.get(imageURL))
|
||||
}
|
||||
|
||||
func testCacheObjectInheritance() throws {
|
||||
class ParentObject {
|
||||
let value: String
|
||||
|
||||
init(value: String) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
class SubclassObject: ParentObject { }
|
||||
|
||||
let expectedValue = "subclass"
|
||||
let key = UUID()
|
||||
|
||||
let cache: Cache<AnyHashable, ParentObject> = Cache()
|
||||
|
||||
cache.set(value: SubclassObject(value: expectedValue), forKey: key)
|
||||
|
||||
let subclassObject: SubclassObject = try XCTUnwrap(cache.get(key))
|
||||
|
||||
XCTAssertEqual(subclassObject.value, expectedValue)
|
||||
}
|
||||
|
||||
func testJSON() throws {
|
||||
enum MockJSONKey: String, Hashable {
|
||||
case name, number, bool, invalid_key
|
||||
}
|
||||
|
||||
struct MockJSON: Codable {
|
||||
var name: String
|
||||
var number: Int
|
||||
var bool: Bool
|
||||
}
|
||||
|
||||
let jsonData: Data = try! JSONEncoder().encode(MockJSON(name: "OpenBytes", number: 5, bool: false))
|
||||
|
||||
var json: JSON<MockJSONKey> = JSON(data: jsonData)
|
||||
|
||||
XCTAssertEqual(try json.resolve(.name), "OpenBytes")
|
||||
XCTAssertEqual(try json.resolve(.number), 5)
|
||||
XCTAssertEqual(try json.resolve(.bool), false)
|
||||
|
||||
XCTAssertEqual(json.valuesInCache(ofType: String.self).count, 1)
|
||||
XCTAssertEqual(json.valuesInCache(ofType: Int.self).count, 2)
|
||||
XCTAssertEqual(json.valuesInCache(ofType: Bool.self).count, 1)
|
||||
|
||||
let invalid_key: Bool? = json.get(.invalid_key)
|
||||
|
||||
XCTAssertNil(json.get(.invalid_key))
|
||||
XCTAssertNil(invalid_key)
|
||||
|
||||
json.set(value: "Leif", forKey: .name)
|
||||
|
||||
XCTAssertEqual(try json.resolve(.name), "Leif")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue