├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── LICENSE
├── Package.swift
├── README.md
├── Sources
├── SpellbookBinaryParsing
│ ├── BinaryParsingError.swift
│ ├── BinaryReader.swift
│ ├── BinaryReaderInput.swift
│ ├── BinaryWriter.swift
│ └── BinaryWriterOutput.swift
├── SpellbookFoundation
│ ├── Combine
│ │ ├── Extensions - Combine.swift
│ │ └── Proxies - Combine.swift
│ ├── Common
│ │ ├── Benchmark.swift
│ │ ├── CancellationToken.swift
│ │ ├── CollectionDiff.swift
│ │ ├── Environment.swift
│ │ ├── Exceptions.swift
│ │ ├── Extensions - Codable.swift
│ │ ├── Extensions - Collections.swift
│ │ ├── Extensions - Comparable.swift
│ │ ├── Extensions - Formatters.swift
│ │ ├── Extensions - StandardTypes.swift
│ │ ├── SBUnit.swift
│ │ ├── SpellbookLog.swift
│ │ ├── Utils.swift
│ │ ├── ValueBuilder.swift
│ │ └── WildcardExpression.swift
│ ├── DictionaryParsing
│ │ ├── DictionaryCodingKey.swift
│ │ ├── DictionaryReader.swift
│ │ └── DictionaryWriter.swift
│ ├── Errors
│ │ ├── CommonError.swift
│ │ ├── CustomErrorUpdating.swift
│ │ ├── Extensions - Error.swift
│ │ ├── Extensions - NSError.swift
│ │ └── IOKitError.swift
│ ├── Filesystem & Bundle
│ │ ├── Extensions - Bundle.swift
│ │ ├── Extensions - FileManager.swift
│ │ ├── FileEnumerator.swift
│ │ ├── FileStore.swift
│ │ └── TemporaryDirectory.swift
│ ├── GUI
│ │ ├── Extensions - CoreGraphics.swift
│ │ └── RGBColor.swift
│ ├── Internal.swift
│ ├── Low Level
│ │ ├── AuditToken.swift
│ │ ├── BridgedCEnum.swift
│ │ ├── MachTime.swift
│ │ ├── POD+Swift.swift
│ │ └── Unsafe.swift
│ ├── Private
│ │ └── _ValueUpdateWrapping.swift
│ ├── System & Hardware
│ │ ├── DeviceInfo.swift
│ │ └── Extensions - ProcessInfo.swift
│ ├── Threading & Concurrency
│ │ ├── Atomic.swift
│ │ ├── BlockingQueue.swift
│ │ ├── ConcurrentBlockOperation.swift
│ │ ├── Extensions - DispatchQueue.swift
│ │ ├── Extensions - Locks.swift
│ │ ├── Extensions - Task.swift
│ │ ├── PosixLocks.swift
│ │ ├── Synchronized.swift
│ │ ├── SynchronizedObjC.swift
│ │ └── SynchronousExecutor.swift
│ ├── Types & PropertyWrappers
│ │ ├── Boxing.swift
│ │ ├── Closure.swift
│ │ ├── Refreshable.swift
│ │ ├── Resource (RAII).swift
│ │ └── Types.swift
│ └── ValueObserving
│ │ ├── EventAsk.swift
│ │ ├── EventNotify.swift
│ │ ├── ValueObservable.swift
│ │ ├── ValueObserving.swift
│ │ ├── ValueStore.swift
│ │ └── ValueView.swift
├── SpellbookFoundationObjC
│ ├── SpellbookObjC.h
│ └── SpellbookObjC.mm
├── SpellbookHTTP
│ ├── HTTPClient.swift
│ ├── HTTPRequest.swift
│ ├── HTTPResult.swift
│ └── HTTPTypes.swift
└── SpellbookTestUtils
│ ├── Extensions - XCTestCase.swift
│ ├── TestError.swift
│ └── Testing.swift
└── Tests
├── SpellbookTestUtilsTests
└── TestingTests.swift
└── SpellbookTests
├── BinaryParsing
└── BinaryParsingTests.swift
├── Common
├── BlockingQueueTests.swift
├── CancellationTokenTests.swift
├── CollectionDiffTests.swift
├── ObjectBuilderTests.swift
├── OtherCommonTests.swift
├── SBLogTests.swift
├── SBUnitTests.swift
├── UtilsTests.swift
└── WildcardExpressionTests.swift
├── DictionaryParsing
└── DictionaryParsingTests.swift
├── Errors
├── CommonErrorTests.swift
├── ErrorExtensionsTests.swift
└── NSErrorTests.swift
├── Extensions Tests
├── CodableTests.swift
├── CollectionsTests.swift
└── StandardTypesTests.swift
├── Filesystem & Bundle
├── FileEnumeratorTests.swift
├── FileManagerTests.swift
├── FileStoreTests.swift
└── TemporaryDirectoryTests.swift
├── GUITests
└── GUITests.swift
├── LowLevel
├── AuditTokenTests.swift
├── MachTests.swift
└── UnsafeTests.swift
├── Observing
├── EventAskTests.swift
├── EventNotifyTests.swift
├── ObservableTests.swift
├── ValueObservingTests.swift
└── ValueStoreTests.swift
├── Other
└── ObjCTests.swift
├── Threading & Concurrency
├── ConcurrentBlockOperationTests.swift
├── DispatchQueueExtensionsTests.swift
└── SynchronousExecutorTests.swift
└── Types & PropertyWrappers
├── PropertyWrapperTests.swift
├── RefreshableTests.swift
├── ResourceTests.swift
└── TypesTests.swift
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: ["main"]
6 | pull_request:
7 | branches: "*"
8 |
9 | jobs:
10 | build:
11 | strategy:
12 | matrix:
13 | include:
14 | - xcode: "16.2" # Swift 6
15 | macOS: "15"
16 | iOS: "17.0"
17 | fail-fast: false
18 |
19 | runs-on: macos-${{ matrix.macOS }}
20 | name: Build with Xcode ${{ matrix.xcode }} on macOS ${{ matrix.macOS }}
21 |
22 | steps:
23 | - uses: actions/checkout@v3
24 |
25 | - name: Xcode Select Version
26 | uses: mobiledevops/xcode-select-version-action@v1
27 | with:
28 | xcode-select-version: ${{ matrix.xcode }}
29 | - run: xcodebuild -version
30 |
31 | - name: Test macOS with Xcode ${{ matrix.xcode }}
32 | run: |
33 | set -e
34 | set -o pipefail
35 |
36 | xcodebuild test -scheme SwiftSpellbook-Package -destination "platform=macOS" SWIFT_ACTIVE_COMPILATION_CONDITIONS="SPELLBOOK_SLOW_CI_x20" | xcpretty
37 |
38 | # Temporary disabled
39 | # - name: Test iOS with Xcode ${{ matrix.xcode }}
40 | # run: |
41 | # set -e
42 | # set -o pipefail
43 |
44 | # xcodebuild test -scheme SwiftSpellbook-Package -sdk iphonesimulator -destination "$IOS_DEVICE" SWIFT_ACTIVE_COMPILATION_CONDITIONS="SPELLBOOK_SLOW_CI_x20" | xcpretty
45 | # env:
46 | # IOS_DEVICE: "platform=iOS Simulator,OS=${{ matrix.iOS }},name=iPhone 14"
47 |
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Alkenso (Vladimir Vashurkin)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.9
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "SwiftSpellbook",
8 | platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6)],
9 | products: [
10 | .library(
11 | name: "SpellbookFoundation",
12 | targets: ["SpellbookFoundation"]
13 | ),
14 | .library(
15 | name: "SpellbookHTTP",
16 | targets: ["SpellbookHTTP"]
17 | ),
18 | .library(
19 | name: "SpellbookBinaryParsing",
20 | targets: ["SpellbookBinaryParsing"]
21 | ),
22 | .library(
23 | name: "SpellbookTestUtils",
24 | targets: ["SpellbookTestUtils"]
25 | ),
26 | ],
27 | dependencies: [
28 | ],
29 | targets: [
30 | .target(
31 | name: "SpellbookFoundation",
32 | dependencies: ["_SpellbookFoundationObjC"],
33 | linkerSettings: [
34 | .linkedLibrary("bsm", .when(platforms: [.macOS])),
35 | ]
36 | ),
37 | .target(
38 | name: "_SpellbookFoundationObjC",
39 | path: "Sources/SpellbookFoundationObjC",
40 | publicHeadersPath: "."
41 | ),
42 | .target(
43 | name: "SpellbookHTTP",
44 | dependencies: ["SpellbookFoundation"]
45 | ),
46 | .target(
47 | name: "SpellbookBinaryParsing",
48 | dependencies: ["SpellbookFoundation"]
49 | ),
50 | .target(
51 | name: "SpellbookTestUtils",
52 | dependencies: ["SpellbookFoundation"]
53 | ),
54 | .testTarget(
55 | name: "SpellbookTests",
56 | dependencies: ["SpellbookFoundation", "SpellbookBinaryParsing", "SpellbookTestUtils"]
57 | ),
58 | .testTarget(
59 | name: "SpellbookTestUtilsTests",
60 | dependencies: ["SpellbookFoundation", "SpellbookTestUtils"]
61 | ),
62 | ]
63 | )
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftSpellbook
2 | SwiftSpellbook is collection of additions to Swift standard library that makes development easier.
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | If you've found this or other my libraries helpful, please buy me some pizza
12 |
13 |
14 |
15 | ## Motivation
16 | While participating in many projects (macOS and iOS) I use the same tools and standard types extensions.
17 | Once I've decided stop to copy-paste code from project to project and make single library that covers lots of developer needs in utility code.
18 |
19 | ## Content
20 | At top level, the code is organized into libraries that cover big areas.
21 | Now there are only two:
22 | - SpellbookFoundation: utility code
23 | - SpellbookBinaryParsing: convenient way to read and write binary data byte-by-byte
24 | - SpellbookHTTP: HTTP client
25 | - SpellbookTestUtils: utility code frequently used for Unit-Tests
26 |
27 | ## SpellbookFoundation
28 | The most of utility code lives here.
29 | - Combine: Combine.framework extensions
30 | - Common: Mix of commonly used entities
31 | - DictionaryParsing: deal with data nested deeply in dictionaries
32 | - Filesystem & Bundle: FileManager, Bundle and same utilities
33 | - GUI: CoreGraphics utilities. This is NOT an AppKit/UIKit/SwiftUI
34 | - Low Level: extensions to deal with (popular) C structures, unsafe types, etc.
35 | - ObjC Bridging: Caching Objective-C and C++ exceptions from Swift code
36 | - System & Hardware: UNIX and Process utilities
37 | - Threading & Concurrency: utilities that make multithead development easier
38 | - Types & PropertyWrappers: misc types and property wrappers
39 | - ValueObserving: utilities that allows observe and modify-with-observe on any types
40 |
41 | # Other
42 | If you've found this or other my libraries helpful, you could buy me some pizza
43 |
44 |
45 |
46 | You can also find Swift libraries for macOS / *OS development
47 | - [sXPC](https://github.com/Alkenso/sXPC): type-safe wrapper around NSXPCConnection and proxy object
48 | - [sLaunchctl](https://github.com/Alkenso/sLaunchctl): register and manage daemons and user-agents
49 | - [sMock](https://github.com/Alkenso/sMock): Swift unit-test mocking framework similar to gtest/gmock
50 | - [sEndpointSecurity](https://github.com/Alkenso/sEndpointSecurity.git) Swift wrapper around EndpointSecurity.framework
51 | - [SwiftSpellbook_macOS](https://github.com/Alkenso/SwiftSpellbook_macOS) macOS-related collection of additions to Swift standard library that makes development easier.
52 |
--------------------------------------------------------------------------------
/Sources/SpellbookBinaryParsing/BinaryParsingError.swift:
--------------------------------------------------------------------------------
1 | // MIT License
2 | //
3 | // Copyright (c) 2021 Alkenso (Vladimir Vashurkin)
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | import Foundation
24 |
25 | public enum BinaryParsingError: Error {
26 | case outOfRange
27 | case notTrivial(String)
28 | }
29 |
30 | internal func ensureTrivial(_ type: T.Type) throws {
31 | if !_isPOD(T.self) { throw BinaryParsingError.notTrivial("\(T.self)") }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/SpellbookBinaryParsing/BinaryReaderInput.swift:
--------------------------------------------------------------------------------
1 | // MIT License
2 | //
3 | // Copyright (c) 2021 Alkenso (Vladimir Vashurkin)
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | import Foundation
24 |
25 | public protocol BinaryReaderInput {
26 | func readBytes(to: UnsafeMutableBufferPointer, offset: Int) throws
27 | func size() throws -> Int
28 | }
29 |
30 | public struct AnyBinaryReaderInput: BinaryReaderInput {
31 | private var _readBytes: (_ to: UnsafeMutableBufferPointer, _ offset: Int) throws -> Void
32 | private var _size: () throws -> Int
33 |
34 | public init(
35 | readBytes: @escaping (UnsafeMutableBufferPointer, Int) throws -> Void,
36 | size: @escaping () throws -> Int
37 | ) {
38 | _readBytes = readBytes
39 | _size = size
40 | }
41 |
42 | public func readBytes(to: UnsafeMutableBufferPointer, offset: Int) throws {
43 | try _readBytes(to, offset)
44 | }
45 |
46 | public func size() throws -> Int {
47 | try _size()
48 | }
49 | }
50 |
51 | extension BinaryReader {
52 | public init(data: Data) {
53 | self.init(
54 | AnyBinaryReaderInput(
55 | readBytes: { dstPtr, offset in
56 | let range = Range(offset: offset, length: dstPtr.count)
57 | if dstPtr.count != data.copyBytes(to: dstPtr, from: range) {
58 | throw BinaryParsingError.outOfRange
59 | }
60 | },
61 | size: { data.count }
62 | )
63 | )
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Sources/SpellbookBinaryParsing/BinaryWriterOutput.swift:
--------------------------------------------------------------------------------
1 | // MIT License
2 | //
3 | // Copyright (c) 2021 Alkenso (Vladimir Vashurkin)
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | import Foundation
24 |
25 | public protocol BinaryWriterOutput: AnyObject {
26 | func writeBytes(from: UnsafeBufferPointer, at offset: Int) throws
27 | func size() throws -> Int
28 | }
29 |
30 | public class AnyBinaryWriterOutput: BinaryWriterOutput {
31 | private var _writeBytes: (_ from: UnsafeBufferPointer, _ offset: Int) throws -> Void
32 | private var _size: () throws -> Int
33 |
34 | public init(
35 | writeBytes: @escaping (UnsafeBufferPointer, Int) throws -> Void,
36 | size: @escaping () -> Int
37 | ) {
38 | _writeBytes = writeBytes
39 | _size = size
40 | }
41 |
42 | public func writeBytes(from: UnsafeBufferPointer, at offset: Int) throws {
43 | try _writeBytes(from, offset)
44 | }
45 |
46 | public func size() throws -> Int {
47 | try _size()
48 | }
49 | }
50 |
51 | public class DataBinaryWriterOutput: BinaryWriterOutput {
52 | public var data: Data
53 |
54 | public init(data: Data = Data()) {
55 | self.data = data
56 | }
57 |
58 | public func writeBytes(from: UnsafeBufferPointer, at offset: Int) throws {
59 | let appendCount = offset + from.count - data.count
60 | if appendCount > 0 {
61 | data += Data(repeating: 0, count: appendCount)
62 | }
63 | data.replaceSubrange(Range(offset: offset, length: from.count), with: from)
64 | }
65 |
66 | public func size() -> Int {
67 | data.count
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Sources/SpellbookFoundation/Combine/Extensions - Combine.swift:
--------------------------------------------------------------------------------
1 | // MIT License
2 | //
3 | // Copyright (c) 2022 Alkenso (Vladimir Vashurkin)
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | import Combine
24 |
25 | extension Publisher {
26 | public func eraseToAnyPublisher(attachingContext context: Any?) -> AnyPublisher