├── .buildkite └── pipeline.yml ├── .github └── workflows │ └── swift.yml ├── .gitignore ├── .justfile ├── .swift-version ├── .swiftformat ├── .swiftlint.yml ├── .swiftpm ├── configuration │ └── Package.resolved └── xcode │ ├── package.xcworkspace │ └── contents.xcworkspacedata │ └── xcshareddata │ └── xcschemes │ ├── Everything-Package.xcscheme │ ├── Everything.xcscheme │ └── EverythingHelpers.xcscheme ├── .vscode └── settings.json ├── LICENSE.md ├── Package.resolved ├── Package.swift ├── README.md ├── Sources ├── Everything │ ├── Algorithms │ │ ├── AStarSearch.swift │ │ ├── BloomFilter.swift │ │ ├── CRC16.swift │ │ ├── Comparison.swift │ │ ├── DamerauLevenshtein.swift │ │ ├── ExponentialMovingAverageIrregular.swift │ │ ├── Heap.swift │ │ ├── OrderedSet.swift │ │ ├── PriorityQueue.swift │ │ ├── Search.swift │ │ └── Visitor.swift │ ├── AppKit │ │ └── AppKit+Extensions.swift │ ├── CSV │ │ ├── CSVDecoder.swift │ │ └── CSVFormatter.swift │ ├── Coding │ │ ├── AnyDecodable.swift │ │ ├── BinaryEncoding.swift │ │ ├── FormEncoder.swift │ │ └── Streams.swift │ ├── Color │ │ ├── CGColor+More.swift │ │ ├── ColorConvertible.swift │ │ ├── ColorParser.swift │ │ └── SystemColorPalette.swift │ ├── Combine │ │ ├── Combine.swift │ │ ├── ConcreteSubscription.swift │ │ ├── DisplayLinkPublisher.swift │ │ └── FSEventPublisher.swift │ ├── Concurrency │ │ ├── Atomic.swift │ │ ├── Concurrency.swift │ │ └── Threading.swift │ ├── CoreLocation │ │ ├── CoreLocation+Extensions.swift │ │ └── CoreLocation+Extensions2.swift │ ├── DataFormatting │ │ └── Converters.swift │ ├── DataStructures │ │ └── IdentifiableSet.swift │ ├── FileSystem │ │ ├── FSPath+Extensions.swift │ │ ├── FSPath.swift │ │ ├── FileBookmarks.swift │ │ └── FileSystem.swift │ ├── FormatStyle.swift │ ├── Foundation │ │ ├── AnyCodingKey.swift │ │ ├── BlockValueTransformer.swift │ │ ├── Casts.swift │ │ ├── CharacterSet+Extensions.swift │ │ ├── Collections+Extensions.swift │ │ ├── Date+Extensions.swift │ │ ├── Errors.swift │ │ ├── FileManager+xattr.swift │ │ ├── Foundation+Misc.swift │ │ ├── NSXML+Extensions.swift │ │ ├── NumberFormatter+Extensions.swift │ │ ├── Optional+Extensions.swift │ │ ├── Padding.swift │ │ ├── Process+Extensions.swift │ │ ├── Scanner+Extensions.swift │ │ ├── Shlex.swift │ │ ├── String+Escaping.swift │ │ ├── String+Extensions.swift │ │ ├── URL+Extensions.swift │ │ ├── UnsafeBufferPointer+Extensions.swift │ │ └── printColumnar.swift │ ├── Functional │ │ └── Functional.swift │ ├── HID │ │ └── VirtualKeyCode.swift │ ├── Math │ │ ├── Clamp.swift │ │ ├── Fuzzy.swift │ │ ├── Lerp.swift │ │ ├── Math.swift │ │ └── signExtend.swift │ ├── Memory │ │ ├── Align.swift │ │ ├── BitRange.swift │ │ ├── BitSet.swift │ │ ├── Bits.swift │ │ ├── Endianness.swift │ │ └── Memory.swift │ ├── Misc │ │ ├── Benchmark.swift │ │ ├── BinaryCoding.swift │ │ ├── Box.swift │ │ ├── Cache.swift │ │ ├── CompositeHash.swift │ │ ├── CustomTupleConvertable.swift │ │ ├── Errno.swift │ │ ├── Hashing.swift │ │ ├── Identified.swift │ │ ├── Logging.swift │ │ ├── LolUID.swift │ │ ├── MachTime.swift │ │ ├── Misc.swift │ │ ├── Named.swift │ │ ├── OutputStream.swift │ │ ├── Random.swift │ │ ├── Tagged+Radians.swift │ │ ├── Tagged.swift │ │ ├── Timestamp.swift │ │ ├── TrivialID.swift │ │ └── Version.swift │ ├── Parsing │ │ ├── CollectionScanner.swift │ │ └── YACharacterSet.swift │ ├── PropertyWrappers │ │ └── PropertyWrappers.swift │ ├── RadixedIntegerFormatStyle.swift │ ├── Scratch │ │ └── Scratch.swift │ └── SwiftUI │ │ ├── Binding+Extensions.swift │ │ ├── Button+Extensions.swift │ │ ├── Image+Extensions.swift │ │ ├── InigoColorPalette.swift │ │ ├── Styles.swift │ │ ├── Styles.swift.gyb │ │ ├── SwiftUI+Extensions.swift │ │ └── ViewAdapter.swift └── EverythingUnsafeConformances │ └── EverythingUnsafeConformances.swift ├── TestPlans └── Everything.xctestplan ├── Tests ├── EverythingTests │ ├── BitRange_Tests.swift │ ├── BitsTests.swift │ ├── CSVTests.swift │ ├── CollectionScannerTests.swift │ ├── CombineTests.swift │ ├── ComparisonTests.swift │ ├── HeapTests.swift │ ├── IdentifiableSetTests.swift │ ├── ParsingTests │ │ └── CharacterSetTests.swift │ ├── PathTests.swift │ ├── ProcessTest.swift │ ├── RandomTests.swift │ ├── SIMDTests.swift │ ├── TaggedTests.swift │ ├── Utilities.swift │ ├── VersionTests.swift │ └── XCTestManifests.swift └── SwiftParsingTests │ ├── CharacterSetTests.swift │ ├── JSONPathParsingTests.swift │ ├── ParserTests.swift │ ├── ScannerTests.swift │ ├── SwiftParsingTests.swift │ ├── SwiftTransformParsingTests.swift │ ├── XCTestManifests.swift │ └── sample.json └── Utilities └── gyb.py /.buildkite/pipeline.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - commands: 3 | - "swift build" 4 | - commands: 5 | - "swift test" 6 | - commands: 7 | - "xcodebuild -scheme 'Everything' -allowProvisioningUpdates -destination 'generic/platform=macOS'" 8 | - commands: 9 | - "xcodebuild -scheme 'Everything' -allowProvisioningUpdates -destination 'generic/platform=iOS'" 10 | - commands: 11 | - "swiftlint lint --quiet" 12 | -------------------------------------------------------------------------------- /.github/workflows/swift.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Swift project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift 3 | 4 | name: Swift 5 | 6 | on: 7 | push: 8 | pull_request: 9 | 10 | jobs: 11 | build: 12 | runs-on: macos-15 13 | steps: 14 | - uses: maxim-lobanov/setup-xcode@v1 15 | with: 16 | xcode-version: 16 17 | - uses: actions/checkout@v3 18 | - name: Build 19 | run: swift build -v 20 | - name: Run tests 21 | run: swift test -v 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/swift 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=swift 3 | 4 | ### Swift ### 5 | # Xcode 6 | # 7 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 8 | 9 | ## User settings 10 | xcuserdata/ 11 | 12 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 13 | *.xcscmblueprint 14 | *.xccheckout 15 | 16 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 17 | build/ 18 | DerivedData/ 19 | *.moved-aside 20 | *.pbxuser 21 | !default.pbxuser 22 | *.mode1v3 23 | !default.mode1v3 24 | *.mode2v3 25 | !default.mode2v3 26 | *.perspectivev3 27 | !default.perspectivev3 28 | 29 | ## Obj-C/Swift specific 30 | *.hmap 31 | 32 | ## App packaging 33 | *.ipa 34 | *.dSYM.zip 35 | *.dSYM 36 | 37 | ## Playgrounds 38 | timeline.xctimeline 39 | playground.xcworkspace 40 | 41 | # Swift Package Manager 42 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 43 | # Packages/ 44 | # Package.pins 45 | # Package.resolved 46 | # *.xcodeproj 47 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 48 | # hence it is not needed unless you have added a package configuration file to your project 49 | # .swiftpm 50 | 51 | .build/ 52 | 53 | # CocoaPods 54 | # We recommend against adding the Pods directory to your .gitignore. However 55 | # you should judge for yourself, the pros and cons are mentioned at: 56 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 57 | # Pods/ 58 | # Add this line if you want to avoid checking in source code from the Xcode workspace 59 | # *.xcworkspace 60 | 61 | # Carthage 62 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 63 | # Carthage/Checkouts 64 | 65 | Carthage/Build/ 66 | 67 | # Accio dependency management 68 | Dependencies/ 69 | .accio/ 70 | 71 | # fastlane 72 | # It is recommended to not store the screenshots in the git repo. 73 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 74 | # For more information about the recommended setup visit: 75 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 76 | 77 | fastlane/report.xml 78 | fastlane/Preview.html 79 | fastlane/screenshots/**/*.png 80 | fastlane/test_output 81 | 82 | # Code Injection 83 | # After new code Injection tools there's a generated folder /iOSInjectionProject 84 | # https://github.com/johnno1962/injectionforxcode 85 | 86 | iOSInjectionProject/ 87 | 88 | # End of https://www.toptal.com/developers/gitignore/api/swift 89 | -------------------------------------------------------------------------------- /.justfile: -------------------------------------------------------------------------------- 1 | set shell := ["/opt/homebrew/bin/fish", "-c"] 2 | sources := "Sources/Everything" 3 | templates := `find "Sources/Everything" -name "*.gyb"` 4 | 5 | default: 6 | @just --list 7 | 8 | generate: 9 | for template in (find {{sources}} -name "*.gyb"); \ 10 | python3 Utilities/gyb.py "$template" > (path change-extension "" "$template"); \ 11 | end 12 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.7 2 | -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | --disable andOperator 2 | --disable emptyBraces 3 | --disable fileHeader 4 | --disable redundantParens 5 | --disable trailingClosures 6 | --enable isEmpty 7 | 8 | --elseposition next-line 9 | --ifdef indent 10 | --patternlet inline 11 | --stripunusedargs closure-only 12 | --closingparen balanced 13 | --wraparguments preserve 14 | --wrapcollections before-first 15 | -------------------------------------------------------------------------------- /.swiftpm/configuration/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "388e1203aa7d5ef762341756acc598f0e386ebb81c5400e025daa7ee152f117d", 3 | "pins" : [ 4 | { 5 | "identity" : "swift-algorithms", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/apple/swift-algorithms", 8 | "state" : { 9 | "revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42", 10 | "version" : "1.2.0" 11 | } 12 | }, 13 | { 14 | "identity" : "swift-numerics", 15 | "kind" : "remoteSourceControl", 16 | "location" : "https://github.com/apple/swift-numerics.git", 17 | "state" : { 18 | "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b", 19 | "version" : "1.0.2" 20 | } 21 | } 22 | ], 23 | "version" : 3 24 | } 25 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.swiftpm/xcode/xcshareddata/xcschemes/Everything-Package.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 57 | 63 | 64 | 65 | 66 | 67 | 72 | 73 | 76 | 77 | 78 | 79 | 81 | 87 | 88 | 89 | 90 | 91 | 101 | 102 | 108 | 109 | 115 | 116 | 117 | 118 | 120 | 121 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /.swiftpm/xcode/xcshareddata/xcschemes/Everything.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 34 | 35 | 36 | 37 | 39 | 45 | 46 | 47 | 48 | 49 | 59 | 60 | 66 | 67 | 73 | 74 | 75 | 76 | 78 | 79 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /.swiftpm/xcode/xcshareddata/xcschemes/EverythingHelpers.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 59 | 61 | 62 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "CCITT", 4 | "Damerau", 5 | "postorder", 6 | "preorder", 7 | "redblobgames" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Jonathan Wight 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "swift-algorithms", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/apple/swift-algorithms", 7 | "state" : { 8 | "revision" : "bcd4f369ac962bc3e5244c9df778739f8f5bdbf1", 9 | "version" : "1.1.0" 10 | } 11 | }, 12 | { 13 | "identity" : "swift-numerics", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/apple/swift-numerics", 16 | "state" : { 17 | "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b", 18 | "version" : "1.0.2" 19 | } 20 | } 21 | ], 22 | "version" : 2 23 | } 24 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 6.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Everything", 7 | platforms: [ 8 | .iOS(.v17), 9 | .macOS(.v14), 10 | .macCatalyst(.v17), 11 | .tvOS(.v17), 12 | .visionOS(.v1), 13 | ], 14 | products: [ 15 | .library(name: "Everything", targets: ["Everything"]), 16 | .library(name: "EverythingUnsafeConformances", targets: ["EverythingUnsafeConformances"]), 17 | ], 18 | dependencies: [ 19 | .package(url: "https://github.com/apple/swift-algorithms", from: "1.1.0"), 20 | ], 21 | targets: [ 22 | .target( 23 | name: "Everything", 24 | dependencies: [ 25 | .product(name: "Algorithms", package: "swift-algorithms"), 26 | 27 | ] 28 | ), 29 | .target(name: "EverythingUnsafeConformances"), 30 | .testTarget(name: "EverythingTests", dependencies: ["Everything"]), 31 | ], 32 | swiftLanguageModes: [.v6] 33 | ) 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Everything 2 | 3 | Literally everything 4 | 5 | This repository and Swift Package is ~~where my Swift source code goes to die~~ a collection of various small functions and types that don't really merit the overhead of me creating and maintaining their own repository. 6 | 7 | You probably should not link to this Swift Package directly as I make no guarantees about backwards compatibility. Instead I suggest you copy and paste the code from this repository into yours if you find any part of it useful. 8 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/AStarSearch.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // swiftlint:disable:next static_operator 4 | private func < (lhs: T?, rhs: T?) -> Bool { 5 | switch (lhs, rhs) { 6 | case (let l?, let r?): 7 | return l < r 8 | 9 | case (nil, _?): 10 | return true 11 | 12 | default: 13 | return false 14 | } 15 | } 16 | 17 | public struct AStarSearch { 18 | public typealias Cost = Int 19 | 20 | public var neighbors: ((Location) -> [Location])! 21 | public var cost: ((Location, Location) -> Cost)! 22 | public var heuristic: ((Location, Location) -> Cost)! 23 | 24 | public init() {} 25 | 26 | // swiftlint:disable identifier_name 27 | public func search(_ start: Location, goal: Location) -> [Location] { 28 | var frontier = PriorityQueue() 29 | frontier.put(start, priority: 0) 30 | 31 | var came_from: [Location: Location] = [:] 32 | var cost_so_far: [Location: Cost] = [:] 33 | 34 | came_from[start] = start 35 | cost_so_far[start] = 0 36 | 37 | while !frontier.isEmpty { 38 | let current = frontier.get()! 39 | 40 | if current == goal { 41 | break 42 | } 43 | 44 | for next in neighbors(current) { 45 | let new_cost = cost_so_far[current]! + cost(current, next) 46 | if cost_so_far[next] == nil || new_cost < cost_so_far[next] { 47 | cost_so_far[next] = new_cost 48 | let priority = new_cost * heuristic(goal, next) 49 | frontier.put(next, priority: priority) 50 | came_from[next] = current 51 | } 52 | } 53 | } 54 | 55 | if came_from[goal] == nil { 56 | return [] 57 | } 58 | 59 | var path: [Location] = [] 60 | var current = goal 61 | while current != start { 62 | if let from = came_from[current] { 63 | path.append(from) 64 | current = from 65 | } 66 | } 67 | return Array(path.reversed()) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/BloomFilter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct BloomFilter { 4 | let count: Int 5 | var storage: [UInt8] 6 | // swiftlint:disable:next opening_brace 7 | var hashFunctions: [(Element) -> Int] = [{ $0.hashValue }] 8 | 9 | init(count: Int) { 10 | self.count = count 11 | storage = [UInt8](repeating: 0, count: count / 8) 12 | } 13 | 14 | func contains(_ member: Element) -> Bool { 15 | for hashFunction in hashFunctions { 16 | let (index, shift) = indexShift(member, hashFunction: hashFunction) 17 | if (storage[index] & 1 << shift) == 0 { 18 | return false 19 | } 20 | } 21 | return true 22 | } 23 | 24 | mutating func insert(_ member: Element) { 25 | for hashFunction in hashFunctions { 26 | let (index, shift) = indexShift(member, hashFunction: hashFunction) 27 | storage[index] |= 1 << shift 28 | } 29 | } 30 | 31 | internal func indexShift(_ member: Element, hashFunction: (Element) -> Int) -> (Int, UInt8) { 32 | let hash = Int(bitPattern: UInt(bitPattern: hashFunction(member)) % UInt(count)) 33 | let index = hash % storage.count 34 | let shift = UInt8(hash / storage.count) 35 | return (index, shift) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/CRC16.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // CRC-16-CCITT X.25 4 | 5 | // TODO: Use DataProtocol 6 | 7 | public struct CRC16 { 8 | public typealias CRCType = UInt16 9 | public internal(set) var crc: CRCType! 10 | 11 | public init() {} 12 | 13 | public static func accumulate(_ buffer: UnsafeBufferPointer, crc: CRCType = 0xFFFF) -> CRCType { 14 | var accum = crc 15 | for b in buffer { 16 | var tmp = CRCType(b) ^ (accum & 0xFF) 17 | tmp = (tmp ^ (tmp << 4)) & 0xFF 18 | accum = (accum >> 8) ^ (tmp << 8) ^ (tmp << 3) ^ (tmp >> 4) 19 | } 20 | return accum 21 | } 22 | 23 | public mutating func accumulate(_ buffer: UnsafeBufferPointer) { 24 | if crc == nil { 25 | crc = 0xFFFF 26 | } 27 | crc = Self.accumulate(buffer, crc: crc) 28 | } 29 | } 30 | 31 | public extension CRC16 { 32 | mutating func accumulate(_ bytes: [UInt8]) { 33 | bytes.withUnsafeBufferPointer { (body: UnsafeBufferPointer) in 34 | accumulate(body) 35 | } 36 | } 37 | 38 | mutating func accumulate(_ string: String) { 39 | string.withCString { (ptr: UnsafePointer) in 40 | let count = Int(strlen(ptr)) 41 | ptr.withMemoryRebound(to: UInt8.self, capacity: count) { ptr in 42 | let buffer = UnsafeBufferPointer(start: ptr, count: count) 43 | accumulate(buffer) 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/Comparison.swift: -------------------------------------------------------------------------------- 1 | public enum Comparison { 2 | case lesser 3 | case equal 4 | case greater 5 | } 6 | 7 | public func compare(_ lhs: T, _ rhs: T) -> Comparison { 8 | if lhs == rhs { 9 | return .equal 10 | } 11 | if lhs < rhs { 12 | return .lesser 13 | } 14 | return .greater 15 | } 16 | 17 | public extension Comparison { 18 | static func comparisonSummary(_ comparisons: [Comparison]) -> Comparison { 19 | for comparison in comparisons { 20 | switch comparison { 21 | case .lesser: 22 | return .lesser 23 | 24 | case .greater: 25 | return .lesser 26 | 27 | case .equal: 28 | continue 29 | } 30 | } 31 | return .equal 32 | } 33 | 34 | init(sequence1 _: Sequence1, _: some Sequence) where Sequence1.Iterator.Element: Comparable { 35 | self = .equal 36 | } 37 | } 38 | 39 | /** 40 | Return the elements of the 2-tuple as an ordered 2-tuple 41 | 42 | - example 43 | let (a,b) = ordered(("B", "A")) 44 | */ 45 | public func ordered(_ tuple: (T, T)) -> (T, T) { 46 | let (lhs, rhs) = tuple 47 | if lhs <= rhs { 48 | return (lhs, rhs) 49 | } 50 | return (rhs, lhs) 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/DamerauLevenshtein.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol StringDifferenceAlgorithm { 4 | static func distance(_ a: String, _ b: String) -> Int 5 | } 6 | 7 | public enum DamerauLevenshteinAlgorithm: StringDifferenceAlgorithm { 8 | public static func distance(_ a: String, _ b: String) -> Int { 9 | distance(Array(a), Array(b)) 10 | } 11 | 12 | public static func distance(_ a: [Character], _ b: [Character]) -> Int { 13 | func len(_ x: [Character]) -> Int { 14 | x.count 15 | } 16 | if min(a.count, b.count) == 0 { 17 | return max(a.count, b.count) 18 | } 19 | let indicator = a[wrapping: -1] == b[wrapping: -1] ? 0 : 1 20 | let new_a = Array(a.dropLast()) 21 | let new_b = Array(b.dropLast()) 22 | let another_a = Array(a.dropLast(2)) 23 | let another_b = Array(b.dropLast(2)) 24 | if len(a) > 1, len(b) > 1, a[wrapping: -1] == b[wrapping: -2], a[wrapping: -2] == b[wrapping: -1] { 25 | return min(distance(a, new_b) + 1, distance(new_a, b) + 1, distance(new_a, new_b) + indicator, distance(another_a, another_b) + 1) 26 | } 27 | return min(distance(new_a, b) + 1, distance(a, new_b) + 1, distance(new_a, new_b) + indicator) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/ExponentialMovingAverageIrregular.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // TODO: This could just be a function that returns a closure. 4 | // https://oroboro.com/irregular-ema/ 5 | public struct ExponentialMovingAverageIrregular: Sendable { 6 | private typealias Sample = (time: Double, value: Double) 7 | 8 | public private(set) var exponentialMovingAverage: Double = 0 9 | private let alpha: Double 10 | private var lastSample: Sample? 11 | 12 | public init(alpha: Double = 0.2) { 13 | self.alpha = alpha 14 | } 15 | 16 | @discardableResult 17 | public mutating func update(time: Double, value: Double) -> Double { 18 | let newMovingAverage: Double 19 | if let lastSample { 20 | let deltaTime = time - lastSample.time 21 | let a = deltaTime / alpha 22 | let u = exp(a * -1) 23 | let v = (1 - u) / a 24 | newMovingAverage = (u * exponentialMovingAverage) + ((v - u) * lastSample.value) + ((1 - v) * value) 25 | } else { 26 | newMovingAverage = value 27 | } 28 | lastSample = (time: time, value: value) 29 | exponentialMovingAverage = newMovingAverage 30 | return exponentialMovingAverage 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/Heap.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // https://en.wikipedia.org/wiki/Binary_heap 4 | public struct BinaryHeap { 5 | public typealias Comparator = (Element, Element) -> Bool 6 | public let comparator: Comparator 7 | 8 | public typealias Storage = [Element] 9 | public var array: Storage = [] 10 | 11 | public init(comparator: @escaping Comparator) { 12 | self.comparator = comparator 13 | } 14 | 15 | public init(values: [Element], comparator: @escaping Comparator) { 16 | array = values 17 | self.comparator = comparator 18 | build(&array) 19 | } 20 | 21 | public var count: Int { 22 | array.count 23 | } 24 | 25 | public mutating func push(_ element: Element) { 26 | assert(valid(array)) 27 | var index = array.count 28 | array.append(element) 29 | while let parentIndex = parentIndexOfElementAtIndex(index) { 30 | if comparator(array[index], array[parentIndex]) { 31 | array.swapAt(index, parentIndex) 32 | index = parentIndex 33 | } else { 34 | break 35 | } 36 | } 37 | assert(valid(array)) 38 | } 39 | 40 | public mutating func pop() -> Element? { 41 | assert(valid(array)) 42 | guard let root = array.first else { 43 | return nil 44 | } 45 | array[0] = array.last! 46 | array.removeLast() 47 | heapify(0) 48 | assert(valid(array)) 49 | return root 50 | } 51 | 52 | public var isEmpty: Bool { 53 | array.isEmpty 54 | } 55 | } 56 | 57 | private extension BinaryHeap { 58 | func parentIndexOfElementAtIndex(_ index: Int) -> Int? { 59 | index < array.count ? (index - 1) / 2 : nil 60 | } 61 | 62 | func childIndicesOfElementAtIndex(_ index: Int) -> (Int?, Int?) { 63 | let lhsIndex = 2 * index + 1 64 | let rhsIndex = 2 * index + 2 65 | return (lhsIndex < array.count ? lhsIndex : nil, rhsIndex < array.count ? rhsIndex : nil) 66 | } 67 | 68 | mutating func heapify(_ index: Int) { 69 | heapify(&array, index) 70 | } 71 | 72 | func heapify(_ elements: inout [Element], _ index: Int) { 73 | let left = 2 * index + 1 74 | let right = 2 * index + 2 75 | var largest = index 76 | if left < elements.count, comparator(elements[left], elements[largest]) { 77 | largest = left 78 | } 79 | if right < elements.count, comparator(elements[right], elements[largest]) { 80 | largest = right 81 | } 82 | if largest != index { 83 | elements.swapAt(index, largest) 84 | heapify(&elements, largest) 85 | } 86 | } 87 | 88 | // TODO: Not working yet. 89 | func build(_ elements: inout [Element]) { 90 | assertionFailure() 91 | 92 | for i in stride(from: elements.count - 1, through: 0, by: -1) { 93 | heapify(&elements, i) 94 | } 95 | } 96 | 97 | func valid(_ elements: [Element], index: Int = 0) -> Bool { 98 | guard !elements.isEmpty else { 99 | return true 100 | } 101 | let (lhs, rhs) = childIndicesOfElementAtIndex(index) 102 | if let lhs { 103 | if comparator(elements[lhs], elements[index]) { 104 | return false 105 | } 106 | if !valid(elements, index: lhs) { 107 | return false 108 | } 109 | } 110 | if let rhs { 111 | if comparator(elements[rhs], elements[index]) { 112 | return false 113 | } 114 | if !valid(elements, index: rhs) { 115 | return false 116 | } 117 | } 118 | return true 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/OrderedSet.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct OrderedSet where Element: Hashable { 4 | internal var set: Set 5 | internal var array: [Element] 6 | 7 | public init() { 8 | set = [] 9 | array = [] 10 | } 11 | } 12 | 13 | extension OrderedSet: Sequence { 14 | public struct Iterator: IteratorProtocol { 15 | internal var base: Array.Iterator 16 | public mutating func next() -> Element? { 17 | base.next() 18 | } 19 | } 20 | 21 | public func makeIterator() -> Iterator { 22 | Iterator(base: array.makeIterator()) 23 | } 24 | } 25 | 26 | extension OrderedSet: Collection { 27 | public struct Index: Comparable { 28 | internal let base: Array.Index 29 | 30 | public static func < (lhs: OrderedSet.Index, rhs: OrderedSet.Index) -> Bool { 31 | lhs.base < rhs.base 32 | } 33 | } 34 | 35 | public var startIndex: Index { 36 | Index(base: array.startIndex) 37 | } 38 | 39 | public var endIndex: Index { 40 | Index(base: array.endIndex) 41 | } 42 | 43 | public subscript(position: Index) -> Element { 44 | array[position.base] 45 | } 46 | 47 | public func index(after i: Index) -> Index { 48 | Index(base: array.index(after: i.base)) 49 | } 50 | 51 | public var isEmpty: Bool { 52 | array.isEmpty 53 | } 54 | 55 | public var count: Int { 56 | array.count 57 | } 58 | } 59 | 60 | // extension OrderedSet: RandomAccessCollection { 61 | // 62 | // } 63 | 64 | extension OrderedSet: SetAlgebra { 65 | public __consuming func union(_ other: __owned OrderedSet) -> OrderedSet { 66 | unimplemented() 67 | } 68 | 69 | public __consuming func intersection(_ other: OrderedSet) -> OrderedSet { 70 | unimplemented() 71 | } 72 | 73 | public __consuming func symmetricDifference(_ other: __owned OrderedSet) -> OrderedSet { 74 | unimplemented() 75 | } 76 | 77 | public mutating func insert(_ newMember: __owned Element) -> (inserted: Bool, memberAfterInsert: Element) { 78 | let result = set.insert(newMember) 79 | if result.inserted { 80 | array.append(newMember) 81 | } 82 | return result 83 | } 84 | 85 | public mutating func remove(_ member: Element) -> Element? { 86 | if let result = set.remove(member) { 87 | array.removeAll { $0 == result } 88 | return result 89 | } 90 | return nil 91 | } 92 | 93 | public mutating func update(with newMember: __owned Element) -> Element? { 94 | unimplemented() 95 | // if let result = set.update(with: newMember) { 96 | // unimplemented() 97 | // } 98 | // else { 99 | // return nil 100 | // } 101 | } 102 | 103 | public mutating func formUnion(_ other: __owned OrderedSet) { 104 | unimplemented() 105 | } 106 | 107 | public mutating func formIntersection(_ other: OrderedSet) { 108 | unimplemented() 109 | } 110 | 111 | public mutating func formSymmetricDifference(_ other: __owned OrderedSet) { 112 | unimplemented() 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/PriorityQueue.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct PriorityQueue { 4 | public var binaryHeap: BinaryHeap<(Element, Priority)> 5 | 6 | public init() { 7 | binaryHeap = BinaryHeap<(Element, Priority)> { 8 | $0.1 < $1.1 9 | } 10 | } 11 | 12 | public var count: Int { 13 | binaryHeap.count 14 | } 15 | 16 | public var isEmpty: Bool { 17 | binaryHeap.isEmpty 18 | } 19 | 20 | public mutating func get() -> Element? { 21 | guard let (element, _) = binaryHeap.pop() else { 22 | return nil 23 | } 24 | return element 25 | } 26 | 27 | public mutating func put(_ element: Element, priority: Priority) { 28 | binaryHeap.push((element, priority)) 29 | } 30 | } 31 | 32 | extension PriorityQueue: Sequence { 33 | public typealias Iterator = PriorityQueueGenerator 34 | public func makeIterator() -> Iterator { 35 | Iterator(queue: self) 36 | } 37 | } 38 | 39 | public struct PriorityQueueGenerator: IteratorProtocol { 40 | public typealias Element = Value 41 | internal var queue: PriorityQueue 42 | public init(queue: PriorityQueue) { 43 | self.queue = queue 44 | } 45 | 46 | public mutating func next() -> Element? { 47 | queue.get() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/Search.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // http: //www.redblobgames.com/pathfinding/a-star/introduction.html 4 | // http: //www.redblobgames.com/pathfinding/a-star/implementation.html#sec-1-3 5 | 6 | public func breadth_first_search(_ start: Location, goal: Location, neighbors: (Location) -> [Location]) -> [Location] { 7 | var frontier = [Location]() 8 | frontier.put(start) 9 | // var came_from: [Location: Location!] = [start: nil] 10 | var came_from: [Location: Location] = [:] 11 | 12 | while frontier.isEmpty == false { 13 | let current = frontier.get()! 14 | if current == goal { 15 | break 16 | } 17 | for next in neighbors(current) where came_from[next] == nil { 18 | frontier.put(next) 19 | came_from[next] = current 20 | } 21 | } 22 | 23 | if came_from[goal] == nil { 24 | return [] 25 | } 26 | 27 | var path: [Location] = [] 28 | var current = goal 29 | while current != start { 30 | if let from = came_from[current] { 31 | path.append(from) 32 | current = from 33 | } 34 | } 35 | return Array(path.reversed()) 36 | } 37 | 38 | // MARK: - 39 | 40 | private extension Array { 41 | mutating func put(_ newElement: Element) { 42 | append(newElement) 43 | } 44 | 45 | // Complexity O(count) 46 | mutating func get() -> Element? { 47 | guard let element = first else { 48 | return nil 49 | } 50 | remove(at: 0) 51 | return element 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/Everything/Algorithms/Visitor.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Visitor: Sequence where Children: Sequence, Children.Element == Node { 4 | public enum Order { 5 | case preorder // (self, children) 6 | case postorder // (children, self) 7 | } 8 | 9 | let _makeIterator: () -> AnyIterator 10 | 11 | public init(root: Node, children: KeyPath, order: Order = .preorder) { 12 | switch order { 13 | case .preorder: 14 | _makeIterator = { 15 | var stack: [Node] = [] 16 | var current: Node? = root 17 | return AnyIterator { 18 | guard !stack.isEmpty || current != nil else { 19 | return nil 20 | } 21 | let result = current 22 | // TODO: .reversed() is inefficient 23 | stack.append(contentsOf: current![keyPath: children].reversed()) 24 | current = stack.popLast() 25 | return result 26 | } 27 | } 28 | 29 | case .postorder: 30 | // TODO: BROKEN - returns in reverse order 31 | _makeIterator = { 32 | var out: [Node] = [] 33 | var s: [Node] = [root] 34 | return AnyIterator { 35 | if !out.isEmpty { 36 | return out.popLast() 37 | } 38 | if !s.isEmpty { 39 | let current = s.popLast() 40 | out.append(current!) 41 | s.append(contentsOf: current![keyPath: children]) 42 | return out.popLast() 43 | } 44 | return nil 45 | } 46 | } 47 | } 48 | } 49 | 50 | public func makeIterator() -> AnyIterator { 51 | _makeIterator() 52 | } 53 | } 54 | 55 | private extension Array { 56 | mutating func popFirst() -> Element? { 57 | defer { 58 | self = Array(self.dropFirst()) 59 | } 60 | return first 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Everything/AppKit/AppKit+Extensions.swift: -------------------------------------------------------------------------------- 1 | #if os(macOS) 2 | import AppKit 3 | import Foundation 4 | 5 | public extension NSStoryboard { 6 | convenience init(name: String) { 7 | self.init(name: name, bundle: nil) 8 | } 9 | } 10 | #endif // os(macOS) 11 | -------------------------------------------------------------------------------- /Sources/Everything/CSV/CSVDecoder.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct CSVDecoder { 4 | } 5 | 6 | public struct CSVReader { 7 | let data: Data 8 | public enum LineEnding { 9 | case CR 10 | case LF 11 | case CRLF 12 | } 13 | 14 | let lineEndings: LineEnding 15 | 16 | public init(data: Data, lineEndings: LineEnding = .CRLF) { 17 | self.data = data 18 | self.lineEndings = lineEndings 19 | } 20 | 21 | public init(url: URL, lineEndings: LineEnding = .CRLF) throws { 22 | let data = try Data(contentsOf: url, options: .mappedIfSafe) 23 | self = Self(data: data, lineEndings: lineEndings) 24 | // TODO: Dont ignore BOM on other encodings 25 | } 26 | 27 | public func makeIterator() -> AnyIterator<[String]> { 28 | let lineEndings: [UInt8] 29 | switch self.lineEndings { 30 | case .LF: 31 | lineEndings = [0x0A] 32 | 33 | case .CR: 34 | lineEndings = [0x0D] 35 | 36 | case .CRLF: 37 | lineEndings = [0x0D, 0x0A] 38 | } 39 | 40 | var fileScanner = CollectionScanner(elements: data) 41 | 42 | // MS Excel inserts a BOM even for UTF-8 files. 43 | _ = fileScanner.scan(value: [0xEF, 0xBB, 0xBF]) 44 | 45 | let lineIterator = fileScanner.iterator(forComponentsSeparatedBy: lineEndings) 46 | return AnyIterator<[String]> { 47 | guard let line = lineIterator.next() else { 48 | return nil 49 | } 50 | let lineString = String(decoding: line, as: UTF8.self) 51 | var lineScanner = CollectionScanner(elements: lineString) 52 | // TODO: Handle quotes and escapes and all that jazz. UNIT TESTS 53 | return lineScanner.scanCSVFields() 54 | } 55 | } 56 | } 57 | 58 | public struct CSVDictReader { 59 | let reader: CSVReader 60 | 61 | public init(data: Data, lineEndings: CSVReader.LineEnding = .CRLF) { 62 | reader = CSVReader(data: data, lineEndings: lineEndings) 63 | } 64 | 65 | public init(url: URL, lineEndings: CSVReader.LineEnding = .CRLF) throws { 66 | reader = try CSVReader(url: url, lineEndings: lineEndings) 67 | } 68 | 69 | public func makeIterator() -> AnyIterator<[String: String]> { 70 | let recordIterator = reader.makeIterator() 71 | guard let keys = recordIterator.next() else { 72 | return NilIterator().eraseToAnyIterator() 73 | } 74 | return AnyIterator { 75 | guard let values = recordIterator.next() else { 76 | return nil 77 | } 78 | return Dictionary(uniqueKeysWithValues: zip(keys, values)) 79 | } 80 | } 81 | } 82 | 83 | public struct SharedKeys { 84 | let keys: [Key] 85 | } 86 | 87 | public struct SharedKeysDictionary { 88 | let keys: SharedKeys 89 | let values: [Value] 90 | } 91 | 92 | public extension CollectionScanner { 93 | mutating func scanCSVFields() -> [String] where C == String { 94 | var fields: [String] = [] 95 | while !atEnd { 96 | assertChange(value: current) { 97 | if scan(value: "\"") { 98 | var field = "" 99 | while !atEnd { 100 | if let chunk = scanUpTo(value: "\"").map(String.init) { 101 | field.append(chunk) 102 | } 103 | _ = scan(value: "\"") 104 | if peek() == "\"" { 105 | _ = scan(value: "\"") 106 | field.append("\"") 107 | } else { 108 | fields.append(field) 109 | break 110 | } 111 | } 112 | } else if let field = scanUpTo(value: ",").map(String.init) { 113 | fields.append(field) 114 | } 115 | if scan(value: ",") { 116 | if atEnd { 117 | fields.append("") 118 | } 119 | } 120 | } 121 | } 122 | return fields 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Sources/Everything/CSV/CSVFormatter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct CSVFormatter { 4 | public struct Options { 5 | public var quote: String = "\"" 6 | public var delimiter: String = "," 7 | public var recordDelimiter: String = "\n" 8 | 9 | public enum QuoteLevel { 10 | case none 11 | case all 12 | case minimal 13 | case nonnumeric 14 | } 15 | 16 | public var quoteLevel: QuoteLevel = .minimal 17 | public var doubleQuote = true 18 | public var escape: String? 19 | public var skipInitialSpace = false 20 | 21 | public init() { 22 | } 23 | } 24 | 25 | public var options = Options() 26 | 27 | public init(options: Options = Options()) { 28 | self.options = options 29 | } 30 | 31 | public func formatField(_ field: String) -> String { 32 | let specials = options.quote + options.delimiter + options.recordDelimiter 33 | var field = field 34 | let quote: Bool 35 | switch options.quoteLevel { 36 | case .none: 37 | quote = false 38 | 39 | case .all, .nonnumeric: 40 | quote = true 41 | 42 | case .minimal: 43 | quote = field.contains { 44 | specials.contains($0) 45 | } 46 | } 47 | 48 | if quote && options.doubleQuote { 49 | field = field.replacingOccurrences(of: options.quote, with: options.quote + options.quote) 50 | } else if let escape = options.escape, options.quoteLevel == .none { 51 | field = field.replacingOccurrences(of: escape, with: escape + escape) 52 | field = field.replacingOccurrences(of: options.quote, with: escape + options.quote) 53 | field = field.replacingOccurrences(of: options.delimiter, with: escape + options.delimiter) 54 | field = field.replacingOccurrences(of: options.recordDelimiter, with: escape + options.recordDelimiter) 55 | } 56 | return quote ? options.quote + field + options.quote : field 57 | } 58 | 59 | public func formatFields(_ fields: [String]) -> String { 60 | fields.map { 61 | formatField($0) 62 | } 63 | .joined(separator: options.delimiter) 64 | + options.recordDelimiter 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/Everything/Coding/AnyDecodable.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct AnyDecodable: Decodable { 4 | public var value: Any 5 | 6 | private struct CodingKeys: CodingKey { 7 | var stringValue: String 8 | var intValue: Int? 9 | init?(intValue: Int) { 10 | stringValue = "\(intValue)" 11 | self.intValue = intValue 12 | } 13 | 14 | init?(stringValue: String) { self.stringValue = stringValue } 15 | } 16 | 17 | public init(from decoder: Decoder) throws { 18 | if let container = try? decoder.container(keyedBy: CodingKeys.self) { 19 | var result = [String: Any]() 20 | try container.allKeys.forEach { key throws in 21 | result[key.stringValue] = try container.decode(Self.self, forKey: key).value 22 | } 23 | value = result 24 | } else if var container = try? decoder.unkeyedContainer() { 25 | var result = [Any]() 26 | while !container.isAtEnd { 27 | result.append(try container.decode(Self.self).value) 28 | } 29 | value = result 30 | } else if let container = try? decoder.singleValueContainer() { 31 | if let intVal = try? container.decode(Int.self) { 32 | value = intVal 33 | } else if let doubleVal = try? container.decode(Double.self) { 34 | value = doubleVal 35 | } else if let boolVal = try? container.decode(Bool.self) { 36 | value = boolVal 37 | } else if let stringVal = try? container.decode(String.self) { 38 | value = stringVal 39 | } else { 40 | throw DecodingError.dataCorruptedError(in: container, debugDescription: "the container contains nothing serialisable") 41 | } 42 | } else { 43 | throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not serialise")) 44 | } 45 | } 46 | } 47 | 48 | //let json = """ 49 | //{ 50 | //"id": 12345, 51 | //"name": "Giuseppe", 52 | //"last_name": "Lanza", 53 | //"age": 31, 54 | //"happy": true, 55 | //"rate": 1.5, 56 | //"classes": ["maths", "phisics"], 57 | //"dogs": [ 58 | //{ 59 | //"name": "Gala", 60 | //"age": 1 61 | //}, { 62 | //"name": "Aria", 63 | //"age": 3 64 | //} 65 | //] 66 | //} 67 | //""" 68 | 69 | // func test() { 70 | // let jsonData = json.data(using: .utf8)! 71 | // let stud = try! JSONDecoder().decode(AnyDecodable.self, from: jsonData).value as! [String: Any] 72 | // print(stud) 73 | // } 74 | -------------------------------------------------------------------------------- /Sources/Everything/Coding/BinaryEncoding.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func encode(_ N: UInt64) -> [UInt8] { 4 | var result: [UInt8] = [] 5 | var N = N 6 | repeat { 7 | let byte = UInt8(N & 0b0111_1111) 8 | N = N >> 7 9 | print(N) 10 | result.insert(byte | (N != 0 ? 128 : 0), at: 0) 11 | } 12 | while N > 0 13 | return result 14 | } 15 | -------------------------------------------------------------------------------- /Sources/Everything/Coding/FormEncoder.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct FormEncoder: Encoder { 5 | public var codingPath: [CodingKey] = [] 6 | 7 | public var userInfo: [CodingUserInfoKey: Any] = [:] 8 | 9 | public init() { 10 | } 11 | 12 | public func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key: CodingKey { 13 | KeyedEncodingContainer(MyKeyedEncodingContainer()) 14 | } 15 | 16 | public func unkeyedContainer() -> UnkeyedEncodingContainer { 17 | unimplemented() 18 | } 19 | 20 | public func singleValueContainer() -> SingleValueEncodingContainer { 21 | unimplemented() 22 | } 23 | 24 | // MARK: - 25 | 26 | struct MyKeyedEncodingContainer: KeyedEncodingContainerProtocol where Key: CodingKey { 27 | var codingPath: [CodingKey] = [] 28 | 29 | var views: [AnyView] = [] 30 | 31 | mutating func encodeNil(forKey key: Key) throws { 32 | unimplemented() 33 | } 34 | 35 | mutating func encode(_ value: Bool, forKey key: Key) throws { 36 | unimplemented() 37 | } 38 | 39 | mutating func encode(_ value: String, forKey key: Key) throws { 40 | unimplemented() 41 | } 42 | 43 | mutating func encode(_ value: Double, forKey key: Key) throws { 44 | let view = HStack { 45 | Text(key.stringValue) 46 | Text(String(describing: value)) 47 | } 48 | views.append(AnyView(view)) 49 | } 50 | 51 | mutating func encode(_ value: Float, forKey key: Key) throws { 52 | unimplemented() 53 | } 54 | 55 | mutating func encode(_ value: Int, forKey key: Key) throws { 56 | unimplemented() 57 | } 58 | 59 | mutating func encode(_ value: Int8, forKey key: Key) throws { 60 | unimplemented() 61 | } 62 | 63 | mutating func encode(_ value: Int16, forKey key: Key) throws { 64 | unimplemented() 65 | } 66 | 67 | mutating func encode(_ value: Int32, forKey key: Key) throws { 68 | unimplemented() 69 | } 70 | 71 | mutating func encode(_ value: Int64, forKey key: Key) throws { 72 | unimplemented() 73 | } 74 | 75 | mutating func encode(_ value: UInt, forKey key: Key) throws { 76 | unimplemented() 77 | } 78 | 79 | mutating func encode(_ value: UInt8, forKey key: Key) throws { 80 | unimplemented() 81 | } 82 | 83 | mutating func encode(_ value: UInt16, forKey key: Key) throws { 84 | unimplemented() 85 | } 86 | 87 | mutating func encode(_ value: UInt32, forKey key: Key) throws { 88 | unimplemented() 89 | } 90 | 91 | mutating func encode(_ value: UInt64, forKey key: Key) throws { 92 | unimplemented() 93 | } 94 | 95 | mutating func encode(_ value: some Encodable, forKey key: Key) throws { 96 | unimplemented() 97 | } 98 | 99 | mutating func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer where NestedKey: CodingKey { 100 | unimplemented() 101 | } 102 | 103 | mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { 104 | unimplemented() 105 | } 106 | 107 | mutating func superEncoder() -> Encoder { 108 | unimplemented() 109 | } 110 | 111 | mutating func superEncoder(forKey key: Key) -> Encoder { 112 | unimplemented() 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Sources/Everything/Coding/Streams.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // public protocol BinaryOutputStream { 4 | // mutating func append(_ value: UInt8) 5 | // mutating func append(_ value: UnsafeBufferPointer) 6 | // mutating func append(_ value: UnsafeRawBufferPointer) 7 | // } 8 | // 9 | //// TODO: We can just make Data/Array conform to this 10 | // public class Output: BinaryOutputStream { 11 | // public var bytes: [UInt8] = [] 12 | // 13 | // public func append(_ value: UInt8) { 14 | // bytes.append(value) 15 | // } 16 | // 17 | // public func append(_ value: UnsafeBufferPointer) { 18 | // bytes += value 19 | // } 20 | // 21 | // public func append(_ value: UnsafeRawBufferPointer) { 22 | // append(value.bindMemory(to: UInt8.self)) 23 | // } 24 | // } 25 | 26 | // extension Output: CustomStringConvertible { 27 | // public var description: String { 28 | // return String(describing: bytes) 29 | // } 30 | // } 31 | 32 | public protocol OutputStream { 33 | mutating func write(bytes: T) throws where T: Collection, T.Element == UInt8 34 | mutating func write(_ value: String) throws 35 | mutating func write(_ value: T) throws 36 | } 37 | 38 | public class BinaryOutputStream: OutputStream where Buffer: RangeReplaceableCollection, Buffer.Element == UInt8 { 39 | public private(set) var buffer: Buffer 40 | 41 | public enum StringEncodingStrategy { 42 | case undecorated 43 | case nilTerminated 44 | case lengthPrefixed 45 | case custom((BinaryOutputStream, String) throws -> Void) 46 | } 47 | 48 | public var stringEncodingStrategy: StringEncodingStrategy = .undecorated 49 | public var stringEncoding: String.Encoding = .utf8 50 | public var allowLossyStringConversion = false 51 | 52 | var current: Buffer.Index 53 | 54 | public init(buffer: Buffer) { 55 | self.buffer = buffer 56 | current = buffer.startIndex 57 | } 58 | 59 | public func write(bytes: some Collection) throws { 60 | let end = buffer.index(current, offsetBy: bytes.count) 61 | buffer.replaceSubrange(current ..< end, with: bytes) 62 | current = end 63 | } 64 | 65 | public func write(_ value: String) throws { 66 | switch stringEncodingStrategy { 67 | case .undecorated: 68 | guard let data = value.data(using: stringEncoding, allowLossyConversion: allowLossyStringConversion) else { 69 | throw GeneralError.valueConversionFailure 70 | } 71 | try write(bytes: data) 72 | 73 | case .nilTerminated: 74 | guard let data = value.data(using: stringEncoding, allowLossyConversion: allowLossyStringConversion) else { 75 | throw GeneralError.valueConversionFailure 76 | } 77 | try write(bytes: data) 78 | try write(bytes: [UInt8(0)]) 79 | 80 | case .lengthPrefixed: 81 | guard let data = value.data(using: stringEncoding, allowLossyConversion: allowLossyStringConversion) else { 82 | throw GeneralError.valueConversionFailure 83 | } 84 | guard data.count <= 255 else { 85 | throw GeneralError.valueConversionFailure 86 | } 87 | try write(bytes: [UInt8(data.count)]) 88 | try write(bytes: data) 89 | 90 | case .custom(let custom): 91 | try custom(self, value) 92 | } 93 | } 94 | 95 | public func write(_ value: some Any) throws { 96 | try withUnsafeBytes(of: value) { bytes in 97 | try write(bytes: bytes) 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Sources/Everything/Color/CGColor+More.swift: -------------------------------------------------------------------------------- 1 | import CoreGraphics 2 | 3 | #if os(macOS) 4 | import AppKit 5 | #elseif os(iOS) || os(tvOS) 6 | import UIKit 7 | #endif 8 | 9 | public extension CGColor { 10 | #if os(macOS) 11 | static func HSV(hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat = 1.0) -> CGColor { 12 | NSColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha).cgColor 13 | } 14 | 15 | #elseif os(iOS) || os(tvOS) 16 | static func HSV(hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat = 1.0) -> CGColor { 17 | UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha).cgColor 18 | } 19 | #endif 20 | 21 | func withAlphaComponent(_ alpha: CGFloat) -> CGColor { 22 | copy(alpha: alpha)! 23 | } 24 | 25 | func blended(withFraction fraction: CGFloat, of other: CGColor) -> CGColor { 26 | unimplemented() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/Everything/Color/ColorConvertible.swift: -------------------------------------------------------------------------------- 1 | import CoreGraphics 2 | 3 | // TODO: Move 4 | public protocol ColorConvertible { 5 | var color: CGColor { get } 6 | } 7 | 8 | extension Double: ColorConvertible { 9 | public var color: CGColor { 10 | let gray = CGFloat(self) 11 | return CGColor(red: gray, green: gray, blue: gray, alpha: 1.0) 12 | } 13 | } 14 | 15 | extension Bool: ColorConvertible { 16 | public var color: CGColor { 17 | let gray: CGFloat = self ? 1.0 : 0.0 18 | return CGColor(red: gray, green: gray, blue: gray, alpha: 1.0) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/Everything/Color/SystemColorPalette.swift: -------------------------------------------------------------------------------- 1 | import CoreGraphics 2 | 3 | #if os(macOS) 4 | import AppKit 5 | #elseif os(iOS) || os(tvOS) 6 | import UIKit 7 | #endif 8 | 9 | public protocol SystemColorPalette { 10 | associatedtype SystemColor 11 | 12 | static var clear: SystemColor { get } 13 | static var white: SystemColor { get } 14 | static var black: SystemColor { get } 15 | static var red: SystemColor { get } 16 | static var green: SystemColor { get } 17 | static var blue: SystemColor { get } 18 | static var magenta: SystemColor { get } 19 | static var yellow: SystemColor { get } 20 | static var cyan: SystemColor { get } 21 | static var orange: SystemColor { get } 22 | static var purple: SystemColor { get } 23 | 24 | static var darkGray: SystemColor { get } 25 | static var lightGray: SystemColor { get } 26 | static var gray: SystemColor { get } 27 | static var brown: SystemColor { get } 28 | } 29 | 30 | #if os(macOS) 31 | extension NSColor: SystemColorPalette { 32 | public typealias SystemColor = NSColor 33 | } 34 | 35 | extension CGColor: SystemColorPalette { 36 | public typealias SystemColor = CGColor 37 | 38 | public static var red: SystemColor { NSColor.red.cgColor } 39 | public static var green: SystemColor { NSColor.green.cgColor } 40 | public static var blue: SystemColor { NSColor.blue.cgColor } 41 | public static var magenta: SystemColor { NSColor.magenta.cgColor } 42 | public static var yellow: SystemColor { NSColor.yellow.cgColor } 43 | public static var cyan: SystemColor { NSColor.cyan.cgColor } 44 | public static var orange: SystemColor { NSColor.orange.cgColor } 45 | public static var purple: SystemColor { NSColor.purple.cgColor } 46 | 47 | public static var darkGray: SystemColor { NSColor.darkGray.cgColor } 48 | public static var lightGray: SystemColor { NSColor.lightGray.cgColor } 49 | public static var gray: SystemColor { NSColor.gray.cgColor } 50 | public static var brown: SystemColor { NSColor.brown.cgColor } 51 | } 52 | 53 | #elseif os(iOS) || os(tvOS) 54 | extension UIColor: SystemColorPalette { 55 | public typealias SystemColor = UIColor 56 | } 57 | 58 | extension CGColor: SystemColorPalette { 59 | public typealias SystemColor = CGColor 60 | 61 | public static var clear: SystemColor { UIColor.clear.cgColor } 62 | public static var white: SystemColor { UIColor.white.cgColor } 63 | public static var black: SystemColor { UIColor.black.cgColor } 64 | public static var red: SystemColor { UIColor.red.cgColor } 65 | public static var green: SystemColor { UIColor.green.cgColor } 66 | public static var blue: SystemColor { UIColor.blue.cgColor } 67 | public static var magenta: SystemColor { UIColor.magenta.cgColor } 68 | public static var yellow: SystemColor { UIColor.yellow.cgColor } 69 | public static var cyan: SystemColor { UIColor.cyan.cgColor } 70 | public static var orange: SystemColor { UIColor.orange.cgColor } 71 | public static var purple: SystemColor { UIColor.purple.cgColor } 72 | 73 | public static var darkGray: SystemColor { UIColor.darkGray.cgColor } 74 | public static var lightGray: SystemColor { UIColor.lightGray.cgColor } 75 | public static var gray: SystemColor { UIColor.gray.cgColor } 76 | public static var brown: SystemColor { UIColor.brown.cgColor } 77 | } 78 | #endif 79 | -------------------------------------------------------------------------------- /Sources/Everything/Combine/Combine.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | import Foundation 3 | 4 | public extension Publisher where Failure == Never { 5 | // Block only gets the first output from 6 | func block() -> Output { 7 | let done = DispatchSemaphore(value: 0) 8 | var result: Output! 9 | let s = sink { output in 10 | result = output 11 | done.signal() 12 | } 13 | done.wait() 14 | s.cancel() 15 | return result 16 | } 17 | } 18 | 19 | public extension Publisher { 20 | func block() throws -> Output { 21 | let done = DispatchSemaphore(value: 0) 22 | var result: Result? 23 | let s = sink(receiveCompletion: { completion in 24 | switch completion { 25 | case .failure(let error): 26 | result = .failure(error) 27 | 28 | default: 29 | unimplemented() 30 | } 31 | done.signal() 32 | }, receiveValue: { output in 33 | result = .success(output) 34 | done.signal() 35 | }) 36 | done.wait() 37 | s.cancel() 38 | return try result!.get() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Everything/Combine/ConcreteSubscription.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | 3 | public struct ConcreteSubscription: Subscription, Hashable where Failure: Error { 4 | public let combineIdentifier: CombineIdentifier 5 | public let subscriber: AnySubscriber 6 | let _request: ((Self, Subscribers.Demand) -> Void)? 7 | let _cancel: ((Self) -> Void)? 8 | 9 | public init(subscriber: S, request: @escaping (Self, Subscribers.Demand) -> Void, cancel: @escaping (Self) -> Void) where S: Subscriber, S.Input == Output, S.Failure == Failure { 10 | let subscriber = AnySubscriber(subscriber) 11 | combineIdentifier = subscriber.combineIdentifier 12 | self.subscriber = subscriber 13 | _request = request 14 | _cancel = cancel 15 | } 16 | 17 | public func request(_ demand: Subscribers.Demand) { 18 | _request?(self, demand) 19 | } 20 | 21 | public func cancel() { 22 | _cancel?(self) 23 | } 24 | 25 | public static func == (lhs: Self, rhs: Self) -> Bool { 26 | lhs.combineIdentifier == rhs.combineIdentifier 27 | } 28 | 29 | public func hash(into hasher: inout Hasher) { 30 | combineIdentifier.hash(into: &hasher) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Everything/Concurrency/Atomic.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import os 3 | 4 | @available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) 5 | @propertyWrapper 6 | public struct Atomic where Value: Sendable { 7 | var lock: OSAllocatedUnfairLock 8 | 9 | public init(wrappedValue: Value) { 10 | lock = .init(initialState: wrappedValue) 11 | } 12 | 13 | public var wrappedValue: Value { 14 | get { 15 | lock.withLock { value in 16 | value 17 | } 18 | } 19 | set { 20 | lock.withLock { value in 21 | value = newValue 22 | } 23 | } 24 | } 25 | } 26 | 27 | @available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) 28 | @propertyWrapper 29 | public struct UncheckedAtomic { 30 | var lock: OSAllocatedUnfairLock 31 | var _wrappedValue: Value 32 | 33 | public init(wrappedValue: Value) { 34 | lock = .init() 35 | _wrappedValue = wrappedValue 36 | } 37 | 38 | public var wrappedValue: Value { 39 | get { 40 | lock.withLockUnchecked { 41 | _wrappedValue 42 | } 43 | } 44 | set { 45 | lock.withLockUnchecked { 46 | _wrappedValue = newValue 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/Everything/Concurrency/Concurrency.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MainActor { 4 | static func runTask(_ block: @MainActor @Sendable @escaping () -> Void) { 5 | Task { 6 | await Self.run { 7 | block() 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/Everything/Concurrency/Threading.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol Locking { 4 | mutating func lock() 5 | mutating func unlock() 6 | } 7 | 8 | // MARK: - 9 | 10 | public extension Locking { 11 | mutating func with(closure: () throws -> R) rethrows -> R { 12 | lock() 13 | defer { 14 | unlock() 15 | } 16 | return try closure() 17 | } 18 | } 19 | 20 | // MARK: - 21 | 22 | extension NSLock: Locking {} 23 | 24 | extension NSRecursiveLock: Locking {} 25 | 26 | public func synchronized(object: AnyObject, closure: () throws -> R) rethrows -> R { 27 | objc_sync_enter(object) 28 | defer { 29 | let result = objc_sync_exit(object) 30 | guard Int(result) == OBJC_SYNC_SUCCESS else { 31 | unimplemented() 32 | } 33 | } 34 | return try closure() 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Everything/CoreLocation/CoreLocation+Extensions.swift: -------------------------------------------------------------------------------- 1 | @preconcurrency import Combine 2 | @preconcurrency import CoreLocation 3 | import Foundation 4 | 5 | final class CoreLocationManager: NSObject, CLLocationManagerDelegate, Sendable { 6 | public static let shared = CoreLocationManager() 7 | 8 | private let manager = CLLocationManager() 9 | 10 | private let _location = PassthroughSubject() 11 | public var location: AnyPublisher { 12 | #if !os(tvOS) 13 | manager.startUpdatingLocation() 14 | #endif 15 | return _location.eraseToAnyPublisher() 16 | } 17 | 18 | // @Publisher var location2: CLLocation 19 | 20 | override public init() { 21 | super.init() 22 | manager.delegate = self 23 | #if os(iOS) || os(tvOS) 24 | manager.requestWhenInUseAuthorization() 25 | #endif 26 | } 27 | 28 | // MARK: - 29 | 30 | public func locationManager(_: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 31 | locations.forEach { 32 | _location.send($0) 33 | } 34 | } 35 | 36 | public func locationManager(_: CLLocationManager, didFailWithError _: Error) { 37 | // unimplemented() 38 | } 39 | } 40 | 41 | public enum LatitudeLongitude: CaseIterable { 42 | case latitude 43 | case longitude 44 | } 45 | 46 | public enum Hemisphere: CaseIterable { 47 | case east 48 | case west 49 | case north 50 | case south 51 | } 52 | 53 | public func hemisphere(for degrees: CLLocationDegrees, latlon: LatitudeLongitude) -> Hemisphere { 54 | switch (degrees >= 0, latlon) { 55 | case (true, .latitude): 56 | return .north 57 | 58 | case (false, .latitude): 59 | return .south 60 | 61 | case (true, .longitude): 62 | return .east 63 | 64 | case (false, .longitude): 65 | return .west 66 | } 67 | } 68 | 69 | extension Hemisphere: CustomStringConvertible { 70 | public var description: String { 71 | switch self { 72 | case .north: 73 | return "n" 74 | case .south: 75 | return "s" 76 | case .east: 77 | return "e" 78 | case .west: 79 | return "w" 80 | } 81 | } 82 | } 83 | 84 | public extension CLLocationCoordinate2D { 85 | var components: [CLLocationDegrees] { 86 | [latitude, longitude] 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Sources/Everything/CoreLocation/CoreLocation+Extensions2.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | @preconcurrency import CoreLocation 3 | 4 | public extension CLGeocoder { 5 | static let shared = CLGeocoder() 6 | 7 | func geocodeAddressString(_ addressString: String) -> AnyPublisher<[CLPlacemark], Error> { 8 | Future<[CLPlacemark], Error> { future in 9 | self.geocodeAddressString(addressString) { placemarks, error in 10 | if let placemarks { 11 | future(.success(placemarks)) 12 | } else if let error { 13 | future(.failure(error)) 14 | } else { 15 | unimplemented() 16 | } 17 | } 18 | } 19 | .eraseToAnyPublisher() 20 | } 21 | 22 | func reverseGeocodeLocation(_ location: CLLocation) -> AnyPublisher<[CLPlacemark], Error> { 23 | Future<[CLPlacemark], Error> { future in 24 | self.reverseGeocodeLocation(location) { placemarks, error in 25 | if let placemarks { 26 | future(.success(placemarks)) 27 | } else if let error { 28 | future(.failure(error)) 29 | } else { 30 | unimplemented() 31 | } 32 | } 33 | } 34 | .eraseToAnyPublisher() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Everything/DataFormatting/Converters.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public protocol Converter { 5 | associatedtype Value 6 | associatedtype Converted 7 | 8 | var convert: (Value) -> Converted { get } 9 | var reverse: (Converted) -> Value { get } 10 | } 11 | 12 | public struct FlippedConverter: Converter where C: Converter { 13 | public typealias Value = C.Converted 14 | public typealias Converted = C.Value 15 | 16 | public let convert: (Value) -> Converted 17 | public let reverse: (Converted) -> Value 18 | 19 | public init(_ converter: C) { 20 | convert = converter.reverse 21 | reverse = converter.convert 22 | } 23 | } 24 | 25 | public extension Converter { 26 | var flipped: FlippedConverter { 27 | FlippedConverter(self) 28 | } 29 | } 30 | 31 | // TODO: Move 32 | public extension Binding { 33 | func converting(converter: C) -> Binding where C: Converter & Sendable, C.Value == Value, Value: Sendable { 34 | Binding( 35 | get: { converter.convert(self.wrappedValue) }, 36 | set: { self.wrappedValue = converter.reverse($0) } 37 | ) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Everything/FileSystem/FSPath+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension FSPath { 4 | func rotate(limit: Int? = nil) throws { 5 | guard exists else { 6 | return 7 | } 8 | guard let parent else { 9 | throw GeneralError.generic("No parent") 10 | } 11 | let destination: FSPath 12 | if let index = Int(pathExtension) { 13 | destination = parent + (stem + ".\(index + 1)") 14 | if let limit { 15 | if index >= limit, exists { 16 | try remove() 17 | return 18 | } 19 | } 20 | } else { 21 | destination = parent + (name + ".1") 22 | } 23 | try destination.rotate(limit: limit) 24 | try move(destination) 25 | } 26 | } 27 | 28 | public extension Bundle { 29 | var resourceFSPath: FSPath? { 30 | resourceURL.map { FSPath($0) } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Everything/FileSystem/FileBookmarks.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | import Foundation 3 | 4 | public struct FileBookmark { 5 | class State { 6 | var bookmarkData: Data? 7 | } 8 | 9 | public let url: URL 10 | let creationOptions: URL.BookmarkCreationOptions 11 | let resolutionOptions: URL.BookmarkResolutionOptions 12 | let state = State() 13 | 14 | public init(url: URL, creationOptions: URL.BookmarkCreationOptions = [], resolutionOptions: URL.BookmarkResolutionOptions = []) throws { 15 | self.url = url 16 | self.creationOptions = creationOptions 17 | self.resolutionOptions = resolutionOptions 18 | if FileManager().fileExists(atPath: url.path) { 19 | state.bookmarkData = try url.bookmarkData(options: creationOptions, includingResourceValuesForKeys: nil, relativeTo: nil) 20 | } 21 | } 22 | 23 | public func resolve() throws -> URL? { 24 | guard let bookmarkData = state.bookmarkData else { 25 | return nil 26 | } 27 | var bookmarkDataIsStale = false 28 | let url = tryElseLog { 29 | try URL(resolvingBookmarkData: bookmarkData, options: resolutionOptions, relativeTo: nil, bookmarkDataIsStale: &bookmarkDataIsStale) 30 | } 31 | if let url, bookmarkDataIsStale { 32 | state.bookmarkData = try url.bookmarkData(options: creationOptions, includingResourceValuesForKeys: nil, relativeTo: nil) 33 | } 34 | return url 35 | } 36 | } 37 | 38 | #if os(macOS) 39 | public class AutoresolvingFileBookmark { 40 | @Published 41 | public private(set) var url: URL 42 | 43 | var bookmark: FileBookmark { 44 | didSet { 45 | url = bookmark.url 46 | } 47 | } 48 | 49 | let creationOptions: URL.BookmarkCreationOptions 50 | let resolutionOptions: URL.BookmarkResolutionOptions 51 | 52 | var publisher: FSEventPublisher? 53 | var cancellable: AnyCancellable? 54 | 55 | public init(url: URL, creationOptions: URL.BookmarkCreationOptions = [], resolutionOptions: URL.BookmarkResolutionOptions = []) throws { 56 | self.url = url 57 | bookmark = try FileBookmark(url: url, creationOptions: creationOptions, resolutionOptions: resolutionOptions) 58 | self.creationOptions = creationOptions 59 | self.resolutionOptions = resolutionOptions 60 | } 61 | 62 | func monitor() throws { 63 | cancellable?.cancel() 64 | let publisher = try FSEventPublisher(paths: [bookmark.url.path], options: [.noDefer, .fileEvents, .watchRoot]) 65 | self.publisher = publisher 66 | cancellable = publisher.sink { _ in 67 | forceTry { 68 | try self.changed() 69 | } 70 | } 71 | } 72 | 73 | func changed() throws { 74 | guard let newURL = try bookmark.resolve() else { 75 | return 76 | } 77 | bookmark = try FileBookmark(url: newURL, creationOptions: creationOptions, resolutionOptions: resolutionOptions) 78 | try monitor() 79 | } 80 | } 81 | 82 | // MARK: - 83 | 84 | public class FileBookmarkFollower { 85 | let bookmark: FileBookmark 86 | 87 | @Published 88 | public var currentURL: URL { 89 | didSet { 90 | forceTry { 91 | try monitor() 92 | } 93 | } 94 | } 95 | 96 | var publisher: FSEventPublisher? 97 | var cancellable: AnyCancellable? 98 | 99 | public init(url: URL) throws { 100 | bookmark = try FileBookmark(url: url) 101 | let resolvedURL = try bookmark.resolve() 102 | currentURL = resolvedURL ?? url 103 | try monitor() 104 | } 105 | 106 | func monitor() throws { 107 | cancellable?.cancel() 108 | let publisher = try FSEventPublisher(paths: [currentURL.path], options: [.noDefer, .fileEvents, .watchRoot]) 109 | self.publisher = publisher 110 | cancellable = publisher.sink { _ in 111 | forceTry { 112 | self.currentURL = try self.bookmark.resolve() ?? self.currentURL 113 | } 114 | } 115 | } 116 | } 117 | #endif 118 | -------------------------------------------------------------------------------- /Sources/Everything/FormatStyle.swift: -------------------------------------------------------------------------------- 1 | // All removed. Use http://github.com/schwa/SwiftFormats 2 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/AnyCodingKey.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum AnyCodingKey: CodingKey, CustomStringConvertible { 4 | case string(String) 5 | case int(Int) 6 | 7 | public init?(stringValue: String) { 8 | self = .string(stringValue) 9 | } 10 | 11 | public init?(intValue: Int) { 12 | self = .int(intValue) 13 | } 14 | 15 | public var stringValue: String { 16 | switch self { 17 | case .string(let value): 18 | return value 19 | 20 | case .int(let value): 21 | return "#\(value)" 22 | } 23 | } 24 | 25 | public var intValue: Int? { 26 | if case .int(let value) = self { 27 | return value 28 | } 29 | fatalError("TODO") 30 | } 31 | 32 | public init(key: some CodingKey) { 33 | if let value = key.intValue { 34 | self = .int(value) 35 | } else { 36 | self = .string(key.stringValue) 37 | } 38 | } 39 | 40 | public var description: String { 41 | switch self { 42 | case .string(let value): 43 | return value 44 | 45 | case .int(let value): 46 | return "#\(value)" 47 | } 48 | } 49 | } 50 | 51 | extension AnyCodingKey: ExpressibleByStringLiteral { 52 | public init(stringLiteral value: StringLiteralType) { 53 | self = .string(value) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/BlockValueTransformer.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class BlockValueTransformer: ValueTransformer { 4 | public typealias TransformerBlock = (AnyObject?) -> (AnyObject?) 5 | 6 | public let block: TransformerBlock 7 | 8 | /* 9 | Generally used: 10 | 11 | BlockValueTransformer.register(name: "Foo") { return Foo($0) } 12 | } 13 | */ 14 | public static func register(_ name: String, block: @escaping TransformerBlock) -> BlockValueTransformer { 15 | let transformer = BlockValueTransformer(block: block) 16 | setValueTransformer(transformer, forName: NSValueTransformerName(rawValue: name)) 17 | return transformer 18 | } 19 | 20 | public init(block: @escaping TransformerBlock) { 21 | self.block = block 22 | } 23 | 24 | override public func transformedValue(_ value: Any?) -> Any? { 25 | block(value as AnyObject?) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Casts.swift: -------------------------------------------------------------------------------- 1 | public struct CastError: Error { 2 | public let message: String? 3 | public let file: StaticString 4 | public let line: UInt 5 | 6 | public init(_ message: @autoclosure () -> String? = nil, file: StaticString = #file, line: UInt = #line) { 7 | self.message = message() 8 | self.file = file 9 | self.line = line 10 | } 11 | } 12 | 13 | public func cast(_ object: some Any, as: T2.Type, _ error: @autoclosure () -> Swift.Error = CastError()) throws -> T2 { 14 | try (object as? T2).safelyUnwrap(error()) 15 | } 16 | 17 | public func forceCast(_ object: some Any, as: T2.Type) -> T2 { 18 | guard let result = object as? T2 else { 19 | fatalError("Could not cast.") 20 | } 21 | return result 22 | } 23 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/CharacterSet+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension CharacterSet { 4 | static let hexdigits = CharacterSet(charactersIn: "0123456789abcdefABCDEF") 5 | } 6 | 7 | public extension CharacterSet { 8 | static func + (lhs: CharacterSet, rhs: CharacterSet) -> CharacterSet { 9 | lhs.union(rhs) 10 | } 11 | } 12 | 13 | public extension CharacterSet { 14 | static func ~= (lhs: CharacterSet, rhs: Character) -> Bool { 15 | lhs.contains(rhs.unicodeScalars.first!) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Date+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Date { 4 | func adding(minutes: Int) -> Date { 5 | Calendar.current.date(byAdding: DateComponents(minute: minutes), to: self)! 6 | } 7 | } 8 | 9 | public extension Date { 10 | static func - (lhs: Date, rhs: Date) -> TimeInterval { 11 | lhs.timeIntervalSince(rhs) 12 | } 13 | 14 | static func + (lhs: Date, rhs: TimeInterval) -> Date { 15 | lhs.addingTimeInterval(rhs) 16 | } 17 | } 18 | 19 | public extension Date { 20 | func startOfDay(in calendar: Calendar? = nil) -> Date { 21 | let calender = calendar ?? Calendar.current 22 | let components = calender.dateComponents([.era, .year, .month, .day, .timeZone], from: self) 23 | return calender.date(from: components)! 24 | } 25 | 26 | func addingDays(_ days: Int, in calendar: Calendar? = nil) -> Date { 27 | let calendar: Calendar = calendar ?? Calendar.current 28 | var components = DateComponents() 29 | components.day = days 30 | return calendar.date(byAdding: components, to: self)! 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/FileManager+xattr.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension FileManager { 4 | func listxattr(for url: URL) -> [String] { 5 | let bufferSize = Darwin.listxattr(url.path, nil, 0, 0) 6 | guard bufferSize > 0 else { 7 | return [] 8 | } 9 | let buffer = ContiguousArray(unsafeUninitializedCapacity: bufferSize) { buffer, size in 10 | buffer.baseAddress!.withMemoryRebound(to: Int8.self, capacity: bufferSize) { pointer in 11 | size = Darwin.listxattr(url.path, pointer, bufferSize, 0) 12 | } 13 | } 14 | return buffer.split(separator: 0).map { String(bytes: $0, encoding: .utf8)! } 15 | } 16 | 17 | func xattr(for url: URL, xattr: String) -> Data { 18 | let bufferSize = getxattr(url.path, xattr, nil, 0, 0, 0) 19 | let buffer = ContiguousArray(unsafeUninitializedCapacity: bufferSize) { buffer, size in 20 | size = getxattr(url.path, xattr, buffer.baseAddress, bufferSize, 0, 0) 21 | } 22 | return Data(buffer) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Foundation+Misc.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension ClosedRange where Bound: FloatingPoint { 4 | var isZero: Bool { 5 | lowerBound == upperBound 6 | } 7 | 8 | func normalize(_ value: Bound) -> Bound { 9 | (value - lowerBound) / (upperBound - lowerBound) 10 | } 11 | } 12 | 13 | public extension UnsafeBufferPointer { 14 | static var elementSize: Int { 15 | Swift.max(MemoryLayout.size, 1) 16 | } 17 | 18 | var byteCount: Int { 19 | count * UnsafeBufferPointer.elementSize 20 | } 21 | } 22 | 23 | public func unsafeBitwiseEquality(_ lhs: T, _ rhs: T) -> Bool { 24 | var lhs = lhs 25 | var rhs = rhs 26 | 27 | return withUnsafePointers(&lhs, &rhs) { 28 | memcmp($0, $1, MemoryLayout.size) == 0 29 | } 30 | } 31 | 32 | private func withUnsafePointers(_ lhs: inout T, _ rhs: inout T, block: (UnsafePointer, UnsafePointer) throws -> R) rethrows -> R { 33 | try withUnsafePointer(to: &lhs) { lhs -> R in 34 | try withUnsafePointer(to: &rhs) { rhs -> R in 35 | try block(lhs, rhs) 36 | } 37 | } 38 | } 39 | 40 | public extension FileManager { 41 | func fileExists(atURL url: URL) -> Bool { 42 | fileExists(atPath: url.path) 43 | } 44 | } 45 | 46 | public extension FileHandle { 47 | var url: Result { 48 | Result { 49 | var filePath = Array(repeating: Int8(0), count: Int(PATH_MAX)) 50 | try filePath.withUnsafeMutableBytes { buffer in 51 | try withPOSIX { 52 | fcntl(fileDescriptor, F_GETPATH, buffer.baseAddress!) 53 | } 54 | } 55 | return URL(fileURLWithFileSystemRepresentation: filePath, isDirectory: false, relativeTo: nil) 56 | } 57 | } 58 | } 59 | 60 | public extension [String: Any] { 61 | func asPlist() -> String { 62 | forceTry { 63 | let d = try PropertyListSerialization.data(fromPropertyList: self, format: .xml, options: 0) 64 | return String(decoding: d, as: UTF8.self) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/NSXML+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if os(macOS) 4 | extension XMLElement { 5 | subscript(name: String) -> XMLNode? { 6 | get { 7 | attribute(forName: name) 8 | } 9 | set { 10 | if let newValue { 11 | assert(name == newValue.name) 12 | addAttribute(newValue) 13 | } else { 14 | removeAttribute(forName: name) 15 | } 16 | } 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/NumberFormatter+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension NumberFormatter { 4 | static var decimalFormatter: NumberFormatter { 5 | let formatter = NumberFormatter() 6 | formatter.maximumFractionDigits = .max 7 | return formatter 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Optional+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Optional { 4 | @discardableResult 5 | func safelyUnwrap(_ error: @autoclosure () -> Swift.Error) throws -> Wrapped { 6 | switch self { 7 | case .none: 8 | throw error() 9 | 10 | case .some(let wrapped): 11 | return wrapped 12 | } 13 | } 14 | 15 | func forceUnwrap(_ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line) -> Wrapped { 16 | switch self { 17 | case .none: 18 | fatalError(message(), file: file, line: line) 19 | 20 | case .some(let wrapped): 21 | return wrapped 22 | } 23 | } 24 | } 25 | 26 | public extension Optional where Wrapped: Collection { 27 | func nilify() -> Wrapped? { 28 | switch self { 29 | case .some(let value): 30 | if value.isEmpty { 31 | return nil 32 | } 33 | return value 34 | 35 | case .none: 36 | return nil 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Padding.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum PaddedPosition { 4 | case start 5 | case end 6 | } 7 | 8 | public extension Array { 9 | func padded(with element: Element, count: Int, position: PaddedPosition) -> Self { 10 | guard self.count < count else { 11 | return self 12 | } 13 | var copy = self 14 | 15 | switch position { 16 | case .start: 17 | copy = repeatElement(element, count: count - self.count) + copy 18 | 19 | case .end: 20 | copy += repeatElement(element, count: count - self.count) 21 | } 22 | return copy 23 | } 24 | } 25 | 26 | public extension String { 27 | func padded(with element: Element, count: Int, position: PaddedPosition) -> Self { 28 | guard self.count < count else { 29 | return self 30 | } 31 | var copy = self 32 | 33 | switch position { 34 | case .start: 35 | copy = repeatElement(element, count: count - self.count) + copy 36 | 37 | case .end: 38 | copy += repeatElement(element, count: count - self.count) 39 | } 40 | return copy 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Scanner+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Scanner { 4 | var remaining: Substring { 5 | string[currentIndex...] 6 | } 7 | 8 | func scan(regularExpression pattern: String) throws -> NSTextCheckingResult? { 9 | let expression = try NSRegularExpression(pattern: pattern, options: []) 10 | let range = NSRange(currentIndex ..< string.endIndex, in: string) 11 | 12 | guard let match = expression.firstMatch(in: string, options: [], range: range) else { 13 | return nil 14 | } 15 | currentIndex = Range(match.range, in: string)!.upperBound 16 | return match 17 | } 18 | 19 | var infographic: String { 20 | "[\(scanned)] <|> [\(remaining)]" 21 | } 22 | 23 | var scanned: Substring { 24 | string[.. String? { 28 | // print("1", Scanner(string: #""kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode' && kMDItemContentType == 'com.apple.application-bundle'""#).scanQuotedEscapedString()) 29 | 30 | // print("1", Scanner(string: #"hello world"#).scanQuotedEscapedString()) 31 | // print("2", Scanner(string: #""hello world""#).scanQuotedEscapedString()) 32 | // print("3", Scanner(string: #""hello \" world""#).scanQuotedEscapedString()) 33 | // print("3", Scanner(string: #""hello \"\" world""#).scanQuotedEscapedString()) 34 | // print("4", Scanner(string: #""hello world"#).scanQuotedEscapedString()) 35 | // print("5", Scanner(string: #"hello "world"#).scanQuotedEscapedString()) 36 | // print("6", Scanner(string: #"hello world""#).scanQuotedEscapedString()) 37 | 38 | let savedIndex = currentIndex 39 | var recover = Optional { 40 | self.currentIndex = savedIndex 41 | } 42 | defer { 43 | recover?() 44 | } 45 | 46 | guard scanString("\"") == "\"" else { 47 | return nil 48 | } 49 | var result = "" 50 | while isAtEnd == false { 51 | guard let s = scanUpToCharacters(from: CharacterSet(charactersIn: "\"\\")) else { 52 | fatalError("This should not be possible.") 53 | } 54 | result.append(s) 55 | 56 | let c = scanCharacter() 57 | 58 | switch c { 59 | case "\\": 60 | let c = scanCharacter() 61 | switch c { 62 | case "\"": 63 | result.append("\"") 64 | 65 | default: 66 | fatalError("Unknown escape code: \(String(describing: c))") 67 | } 68 | case "\"": 69 | break 70 | 71 | default: 72 | return nil 73 | } 74 | } 75 | 76 | recover = nil 77 | return result 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/Shlex.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func shlex(_ string: String) -> [String] { 4 | let scanner = Scanner(string: string) 5 | 6 | var result: [String] = [] 7 | 8 | while scanner.isAtEnd == false { 9 | if let s = scanner.scanQuotedEscapedString() { 10 | result.append(s) 11 | } else if let s = scanner.scanUpToCharacters(from: .whitespaces) { 12 | result.append(s.trimmingCharacters(in: .whitespacesAndNewlines)) 13 | _ = scanner.scanCharacters(from: .whitespaces) 14 | } 15 | } 16 | 17 | return result 18 | } 19 | 20 | public func assertChanging(base: Base, _ keyPath: KeyPath, _ block: () throws -> Result) rethrows -> Result { 21 | let before = base[keyPath: keyPath] 22 | let result = try block() 23 | let after = base[keyPath: keyPath] 24 | assert(before != after) 25 | return result 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/String+Escaping.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension String { 4 | var escaped: String { 5 | unicodeScalars.map { 6 | String($0).isPrintable ? String($0) : $0.escapedString 7 | } 8 | .joined() 9 | } 10 | } 11 | 12 | public extension UnicodeScalar { 13 | var escapedString: String { 14 | switch value { 15 | case 0x00: 16 | return "\\0" 17 | case 0x09: 18 | return "\\t" 19 | case 0x0A: 20 | return "\\n" 21 | case 0x0D: 22 | return "\\r" 23 | case 0x22: 24 | return "\\\"" 25 | case 0x27: 26 | return "\\'" 27 | case 92: 28 | return "\\\\" 29 | case 32 ..< 127: 30 | return String(self) 31 | 32 | default: 33 | return "\\u{\(String(value, radix: 16))}" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/String+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension String { 4 | // TODO: Don't throw. 5 | func substringFromPrefix(_ prefix: String) throws -> Substring { 6 | if prefix.isEmpty { 7 | return self[...] 8 | } 9 | if let range = range(of: prefix), range.lowerBound == startIndex { 10 | return self[range.upperBound...] 11 | } 12 | throw GeneralError.generic("String does not begin with prefix.") 13 | } 14 | } 15 | 16 | public extension String { 17 | func removingOccurances(of characterSet: CharacterSet) -> String { 18 | var result = "" 19 | let scanner = Scanner(string: self) 20 | scanner.charactersToBeSkipped = characterSet 21 | while scanner.isAtEnd == false { 22 | if let chunk = scanner.scanUpToCharacters(from: characterSet) { 23 | result.append(chunk) 24 | } 25 | } 26 | return result 27 | } 28 | } 29 | 30 | public extension StringProtocol { 31 | var isUppercase: Bool { 32 | // TODO: This is very error prone perhaps? 33 | self == uppercased() 34 | } 35 | 36 | var isPrintable: Bool { 37 | let set = CharacterSet.controlCharacters 38 | 39 | return firstIndex { set.contains($0) } == nil 40 | } 41 | } 42 | 43 | extension CharacterSet { 44 | func contains(_ member: Character) -> Bool { 45 | for scalar in member.unicodeScalars { 46 | // TODO: this is a bit iffy. Reverse this logic? 47 | if contains(scalar) { 48 | return true 49 | } 50 | } 51 | return false 52 | } 53 | } 54 | 55 | public extension Character { 56 | static let escape = Character("\u{1B}") 57 | } 58 | 59 | public extension String.Encoding { 60 | init(contentsOf url: URL) throws { 61 | var encoding: String.Encoding = .ascii 62 | _ = try String(contentsOf: url, usedEncoding: &encoding) 63 | self = encoding 64 | } 65 | } 66 | 67 | public extension Character { 68 | static func random(in set: String) -> Character { 69 | set.randomElement()! 70 | } 71 | } 72 | 73 | public extension Character { 74 | init(utf8: UInt8) { 75 | self = Character(UnicodeScalar(utf8)) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/URL+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension URL { 4 | func URLByResolvingURL() throws -> URL { 5 | let bookmarkData = try (self as NSURL).bookmarkData(options: NSURL.BookmarkCreationOptions.minimalBookmark, includingResourceValuesForKeys: nil, relativeTo: nil) 6 | return try (NSURL(resolvingBookmarkData: bookmarkData, options: .withoutUI, relativeTo: nil, bookmarkDataIsStale: nil) as URL) 7 | } 8 | 9 | static func + (lhs: URL, rhs: String) -> URL { 10 | lhs.appendingPathComponent(rhs) 11 | } 12 | 13 | static func += (left: inout URL, right: String) { 14 | // swiftlint:disable:next shorthand_operator 15 | left = left + right 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/UnsafeBufferPointer+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension UnsafeBufferPointer { 4 | init() { 5 | self.init(start: nil, count: 0) 6 | } 7 | 8 | init(start: UnsafePointer, byteCount: Int) { 9 | precondition(byteCount % UnsafeBufferPointer.elementSize == 0) 10 | self.init(start: start, count: byteCount / UnsafeBufferPointer.elementSize) 11 | } 12 | 13 | func withMemoryRebound(to _: T.Type, capacity count: Int, _ body: (UnsafeBufferPointer) throws -> Result) rethrows -> Result { 14 | guard let baseAddress else { 15 | // If base address is nil just return an empty buffer 16 | let buffer = UnsafeBufferPointer() 17 | return try body(buffer) 18 | } 19 | 20 | precondition(((self.count * UnsafeBufferPointer.elementSize) % count) == 0) 21 | 22 | return try baseAddress.withMemoryRebound(to: T.self, capacity: count) { (pointer: UnsafePointer) -> Result in 23 | let buffer = UnsafeBufferPointer(start: pointer, count: count) 24 | return try body(buffer) 25 | } 26 | } 27 | 28 | func withMemoryRebound(_ body: (UnsafeBufferPointer) throws -> Result) rethrows -> Result { 29 | let count = (count * UnsafeBufferPointer.elementSize) / UnsafeBufferPointer.elementSize 30 | return try withMemoryRebound(to: T.self, capacity: count, body) 31 | } 32 | } 33 | 34 | public extension UnsafeMutableBufferPointer { 35 | func toUnsafeBufferPointer() -> UnsafeBufferPointer { 36 | UnsafeBufferPointer(start: baseAddress, count: count) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Everything/Foundation/printColumnar.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func printColumnar(_ columns: Any..., headerRow: Bool = false, leadingSeparator: String = "| ", fieldSeparator: String = " | ", trailingSeparator: String = " |") { 4 | var s = "" 5 | printColumnar(columns, headerRow: headerRow, leadingSeparator: leadingSeparator, fieldSeparator: fieldSeparator, trailingSeparator: trailingSeparator, to: &s) 6 | print(s, terminator: "") 7 | } 8 | 9 | public func printColumnar (_ columns: [Any], headerRow: Bool = false, leadingSeparator: String = "| ", fieldSeparator: String = " | ", trailingSeparator: String = " |", to target: inout Target) where Target: TextOutputStream { 10 | let columns = columns.map { column in 11 | var s = "" 12 | print(column, to: &s) 13 | return s.split(separator: "\n") 14 | } 15 | let columnWidths = columns.map { column in 16 | column.reduce(0) { result, current in 17 | max(result, current.count) 18 | } 19 | } 20 | func printCell(_ cell: (any StringProtocol)?, columnWidth: Int) { 21 | if let cell { 22 | print(cell + String(repeating: " ", count: columnWidth - cell.count), terminator: "", to: &target) 23 | } else { 24 | print(String(repeating: " ", count: columnWidth), terminator: "", to: &target) 25 | } 26 | } 27 | func printRow(cells: [(any StringProtocol)?]) { 28 | print(leadingSeparator, terminator: "", to: &target) 29 | let z = Array(zip(cells, columnWidths)) 30 | if let first = z.first { 31 | printCell(first.0, columnWidth: first.1) 32 | 33 | for (cell, columnWidth) in z.dropFirst() { 34 | print(fieldSeparator, terminator: "", to: &target) 35 | printCell(cell, columnWidth: columnWidth) 36 | } 37 | } 38 | print(trailingSeparator, to: &target) 39 | } 40 | 41 | func printDivider() { 42 | // print(leadingSeparator + String(repeating: "-", count: columnWidths.reduce(0, +) + (columns.count - 1) * (fieldSeparator.count)) + trailingSeparator) 43 | printRow(cells: columnWidths.map { String(repeating: "-", count: $0) }) 44 | } 45 | 46 | printDivider() 47 | var iterators = columns.map { $0.makeIterator() } 48 | var row = 0 49 | while true { 50 | let cells = (iterators.startIndex ..< iterators.endIndex).map { index in 51 | iterators[index].next() 52 | } 53 | guard !cells.allSatisfy({ $0 == nil }) else { 54 | break 55 | } 56 | printRow(cells: cells) 57 | if headerRow && row == 0 { 58 | printDivider() 59 | } 60 | row += 1 61 | } 62 | printDivider() 63 | } 64 | -------------------------------------------------------------------------------- /Sources/Everything/Functional/Functional.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func identity(_ value: Value) -> Value { 4 | value 5 | } 6 | -------------------------------------------------------------------------------- /Sources/Everything/Math/Clamp.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // MARK: Basics 4 | 5 | public func clamp(_ value: T, lower: T, upper: T) -> T where T: Comparable { 6 | max(min(value, upper), lower) 7 | } 8 | 9 | public func clamp(_ value: T, in range: ClosedRange) -> T where T: Comparable { 10 | min(max(value, range.lowerBound), range.upperBound) 11 | } 12 | -------------------------------------------------------------------------------- /Sources/Everything/Math/Fuzzy.swift: -------------------------------------------------------------------------------- 1 | import CoreGraphics 2 | 3 | public func equal(_ lhs: CGFloat, _ rhs: CGFloat, accuracy: CGFloat) -> Bool { 4 | abs(rhs - lhs) <= accuracy 5 | } 6 | 7 | public func equal(_ lhs: Float, _ rhs: Float, accuracy: Float) -> Bool { 8 | abs(rhs - lhs) <= accuracy 9 | } 10 | 11 | public func equal(_ lhs: Double, _ rhs: Double, accuracy: Double) -> Bool { 12 | abs(rhs - lhs) <= accuracy 13 | } 14 | 15 | // MARK: Fuzzy equality 16 | 17 | @available(*, deprecated, message: "Use https://github.com/schwa/ApproximateEquality") 18 | public protocol FuzzyEquatable { 19 | static func ==% (lhs: Self, rhs: Self) -> Bool 20 | } 21 | 22 | infix operator ==%: ComparisonPrecedence 23 | 24 | // MARK: Fuzzy inequality 25 | 26 | infix operator !=%: ComparisonPrecedence 27 | 28 | // swiftlint:disable:next static_operator 29 | @available(*, deprecated, message: "Use https://github.com/schwa/ApproximateEquality") 30 | public func !=% (lhs: T, rhs: T) -> Bool { 31 | !(lhs ==% rhs) 32 | } 33 | 34 | // MARK: Float 35 | 36 | @available(*, deprecated, message: "Use https://github.com/schwa/ApproximateEquality") 37 | extension Float: FuzzyEquatable { 38 | public static func ==% (lhs: Float, rhs: Float) -> Bool { 39 | equal(lhs, rhs, accuracy: .ulpOfOne) 40 | } 41 | } 42 | 43 | // MARK: Double 44 | 45 | @available(*, deprecated, message: "Use https://github.com/schwa/ApproximateEquality") 46 | extension Double: FuzzyEquatable { 47 | public static func ==% (lhs: Double, rhs: Double) -> Bool { 48 | equal(lhs, rhs, accuracy: .ulpOfOne) 49 | } 50 | } 51 | 52 | // MARK: CGFloat 53 | 54 | @available(*, deprecated, message: "Use https://github.com/schwa/ApproximateEquality") 55 | extension CGFloat: FuzzyEquatable { 56 | public static func ==% (lhs: CGFloat, rhs: CGFloat) -> Bool { 57 | equal(lhs, rhs, accuracy: .ulpOfOne) 58 | } 59 | } 60 | 61 | // MARK: CGPoint 62 | 63 | @available(*, deprecated, message: "Use https://github.com/schwa/ApproximateEquality") 64 | extension CGPoint: FuzzyEquatable { 65 | public static func ==% (lhs: CGPoint, rhs: CGPoint) -> Bool { 66 | lhs.x ==% rhs.x && lhs.y ==% rhs.y 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Sources/Everything/Math/Lerp.swift: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Sources/Everything/Math/Math.swift: -------------------------------------------------------------------------------- 1 | import CoreGraphics 2 | import Foundation 3 | 4 | // MARK: Math 5 | 6 | precedencegroup ExponentPrecedence { 7 | associativity: left 8 | higherThan: MultiplicationPrecedence 9 | } 10 | 11 | infix operator **: ExponentPrecedence 12 | 13 | // There is no generic pow<> so we're forced to create one ** for each BinaryFloatingPoint type 14 | 15 | extension Float { 16 | static func ** (lhs: Float, rhs: Float) -> Float { 17 | if rhs == 2 { 18 | return lhs * lhs 19 | } 20 | return pow(lhs, rhs) 21 | } 22 | } 23 | 24 | public extension Double { 25 | static func ** (lhs: Double, rhs: Double) -> Double { 26 | if rhs == 2 { 27 | return lhs * lhs 28 | } 29 | return pow(lhs, rhs) 30 | } 31 | } 32 | 33 | public extension CGFloat { 34 | static func ** (lhs: CGFloat, rhs: CGFloat) -> CGFloat { 35 | if rhs == 2 { 36 | return lhs * lhs 37 | } 38 | return pow(lhs, rhs) 39 | } 40 | } 41 | 42 | // MARK: - 43 | 44 | public func log(_ value: Float, base: Float) -> Float { 45 | log(value) / log(base) 46 | } 47 | 48 | public func log(_ value: Double, base: Double) -> Double { 49 | log(value) / log(base) 50 | } 51 | 52 | // MARK: Degrees/Radians 53 | 54 | // In the spirit of UInt(bigEndian: ) etc 55 | 56 | public extension FloatingPoint { 57 | init(radians: Self) { 58 | self = radians 59 | } 60 | 61 | init(degrees: Self) { 62 | self = degrees * .pi / 180 63 | } 64 | 65 | var radians: Self { 66 | self 67 | } 68 | 69 | var degrees: Self { 70 | self * 180 / .pi 71 | } 72 | } 73 | 74 | // Basic functions 75 | 76 | /* 77 | ```swift doctest 78 | radiansToDegrees(degreesToRadians(90)) // 90 79 | ``` 80 | */ 81 | public func degreesToRadians(_ value: F) -> F where F: FloatingPoint { 82 | value * .pi / 180 83 | } 84 | 85 | public func radiansToDegrees(_ value: F) -> F where F: FloatingPoint { 86 | value * 180 / .pi 87 | } 88 | 89 | // MARK: - 90 | 91 | /* 92 | ```swift doctest 93 | divup(dividend: 10, divisor: 3) // 4 94 | ``` 95 | */ 96 | public func divup(dividend: T, divisor: T) -> T where T: BinaryInteger { 97 | (dividend + (divisor - 1)) / divisor 98 | } 99 | 100 | public func round(_ value: CGFloat, decimal: Int) -> CGFloat { 101 | let e10n = pow(10.0, CGFloat(clamp(decimal, lower: -6, upper: 7))) 102 | let fl = floor(e10n * value + 0.5) 103 | return fl / e10n 104 | } 105 | 106 | public extension Float { 107 | var radiansToDegrees: Self { 108 | Everything.radiansToDegrees(self) 109 | } 110 | 111 | func formatted() -> String { 112 | let f = NumberFormatter() 113 | f.maximumSignificantDigits = 4 114 | return f.string(for: self)! 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Sources/Everything/Math/signExtend.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @inlinable 4 | public func signExtend(_ n: UInt32, bits: Int) -> Int32 { 5 | let signed = (n & 1 << (bits - 1)) != 0 6 | if !signed { 7 | return Int32(truncatingIfNeeded: n) 8 | } 9 | let ones = UInt32.max << bits 10 | return Int32(bitPattern: ones | n) 11 | } 12 | 13 | @inlinable 14 | public func signExtendU(_ n: UInt32, bits: Int) -> UInt32 { 15 | // TODO: this is a bit silly 16 | UInt32(bitPattern: signExtend(n, bits: bits)) 17 | } 18 | 19 | public extension Array { 20 | func rebind(to: T.Type) -> [T] { 21 | withUnsafeBufferPointer { buffer in 22 | let capacity = (count * MemoryLayout.stride) / MemoryLayout.stride 23 | 24 | return buffer.withMemoryRebound(to: T.self, capacity: capacity) { buffer in 25 | [T](buffer) 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Everything/Memory/Align.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | ```swift doctest 5 | align(0, 0) // => Int = 0 6 | ``` 7 | */ 8 | public func align(offset: Int, alignment: Int) -> Int { 9 | // https://en.wikipedia.org/wiki/Data_structure_alignment 10 | let alignment = alignment == 0 ? MemoryLayout.size : alignment 11 | return offset + ((alignment - (offset % alignment)) % alignment) 12 | } 13 | -------------------------------------------------------------------------------- /Sources/Everything/Memory/BitSet.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct BitSet { 4 | public private(set) var count: Int 5 | 6 | public private(set) var elements: [UInt] 7 | internal static let bitsPerElement = MemoryLayout.size * 8 8 | 9 | internal static func minWordsNeededFor(count: Int) -> Int { 10 | Int(ceil(log(Double(count), base: Double(bitsPerElement)))) 11 | } 12 | 13 | public init(count: Int, words: [UInt]) { 14 | assert(count <= words.count * Self.bitsPerElement, "Not enough words (\(words.count)) to store \(count) bits") 15 | assert(words.count <= Self.minWordsNeededFor(count: count), "Need only \(Self.minWordsNeededFor(count: count)) word(s) to store \(count) bits.") 16 | self.count = count 17 | elements = words 18 | } 19 | 20 | public subscript(index: Int) -> UInt { 21 | get { 22 | let element = index / Self.bitsPerElement 23 | let bit = index % Self.bitsPerElement 24 | return elements[element].bits[bit] 25 | } 26 | set { 27 | let element = index / Self.bitsPerElement 28 | let bit = index % Self.bitsPerElement 29 | elements[element].bits[bit] = newValue 30 | } 31 | } 32 | 33 | public subscript(range: ClosedRange) -> Self { 34 | get { 35 | unimplemented() 36 | } 37 | set { 38 | unimplemented() 39 | } 40 | } 41 | } 42 | 43 | public extension BitSet { 44 | init(count: Int) { 45 | self = BitSet(count: count, words: Array(repeating: 0, count: divup(dividend: count, divisor: BitSet.bitsPerElement))) 46 | } 47 | 48 | init(_ value: T) where T: BinaryInteger { 49 | var value = value 50 | self = Swift.withUnsafeBytes(of: &value) { sourceBuffer in 51 | let count = MemoryLayout.size * 8 52 | var elements = Array(repeating: UInt.zero, count: divup(dividend: count, divisor: BitSet.bitsPerElement)) 53 | elements.withUnsafeMutableBytes { destinationBuffer in 54 | _ = sourceBuffer.copyBytes(to: destinationBuffer) 55 | } 56 | return BitSet(count: count, words: elements) 57 | } 58 | } 59 | } 60 | 61 | public extension BitSet { 62 | func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R { 63 | try elements.withUnsafeBytes(body) // TODO: Last word problem 64 | } 65 | 66 | mutating func withUnsafeMutableBytes(_ body: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R { 67 | try elements.withUnsafeMutableBytes(body) // TODO: Last word problem 68 | } 69 | 70 | var bytes: [UInt8] { 71 | unimplemented() 72 | } 73 | } 74 | 75 | public extension BitSet { 76 | static prefix func ~ (bits: BitSet) -> BitSet { 77 | let words = Array(bits.elements.map { ~$0 }) 78 | return BitSet(count: bits.count, words: words) 79 | } 80 | 81 | static func & (lhs: BitSet, rhs: BitSet) -> BitSet { 82 | let words = Array(zip(lhs.elements, rhs.elements).map { $0.0 & $0.1 }) 83 | return BitSet(count: min(lhs.count, rhs.count), words: words) 84 | } 85 | 86 | static func &= (lhs: inout BitSet, rhs: BitSet) { 87 | lhs = lhs & rhs 88 | } 89 | 90 | static func | (lhs: BitSet, rhs: BitSet) -> BitSet { 91 | let words = Array(zip(lhs.elements, rhs.elements).map { $0.0 | $0.1 }) 92 | return BitSet(count: min(lhs.count, rhs.count), words: words) 93 | } 94 | 95 | static func |= (lhs: inout BitSet, rhs: BitSet) { 96 | lhs = lhs | rhs 97 | } 98 | 99 | static func ^ (lhs: BitSet, rhs: BitSet) -> BitSet { 100 | let words = Array(zip(lhs.elements, rhs.elements).map { $0.0 ^ $0.1 }) 101 | return BitSet(count: min(lhs.count, rhs.count), words: words) 102 | } 103 | 104 | static func ^= (lhs: inout BitSet, rhs: BitSet) { 105 | lhs = lhs ^ rhs 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Sources/Everything/Memory/Bits.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @frozen 4 | public struct Bits where T: BinaryInteger { 5 | @usableFromInline 6 | var value: T 7 | 8 | @usableFromInline 9 | init(value: T) { 10 | self.value = value 11 | } 12 | 13 | @usableFromInline 14 | static func mask(lowerBit: Int, upperBit: Int) -> T { 15 | let size = upperBit - lowerBit 16 | return T((2 << size - 1) << lowerBit) 17 | } 18 | 19 | @inlinable 20 | public subscript(range: ClosedRange) -> T { 21 | get { 22 | assert(range.lowerBound >= 0) 23 | assert(range.upperBound < MemoryLayout.size * 8) 24 | let mask = Self.mask(lowerBit: range.lowerBound, upperBit: range.upperBound) 25 | return (value & mask) >> range.lowerBound 26 | } 27 | set { 28 | assert(range.lowerBound >= 0) 29 | assert(range.upperBound < MemoryLayout.size * 8) 30 | let mask = Self.mask(lowerBit: range.lowerBound, upperBit: range.upperBound) 31 | value = value & ~mask | ((newValue << range.lowerBound) & mask) 32 | } 33 | } 34 | } 35 | 36 | public extension Bits { 37 | @inlinable 38 | subscript(range: Range) -> T { 39 | get { 40 | self[ClosedRange(range)] 41 | } 42 | set { 43 | self[ClosedRange(range)] = newValue 44 | } 45 | } 46 | 47 | @inlinable 48 | subscript(range: PartialRangeThrough) -> T { 49 | get { 50 | self[0 ... range.upperBound] 51 | } 52 | set { 53 | self[0 ... range.upperBound] = newValue 54 | } 55 | } 56 | 57 | @inlinable 58 | subscript(range: PartialRangeUpTo) -> T { 59 | get { 60 | self[0 ..< range.upperBound] 61 | } 62 | set { 63 | self[0 ..< range.upperBound] = newValue 64 | } 65 | } 66 | 67 | @inlinable 68 | subscript(range: PartialRangeFrom) -> T { 69 | get { 70 | let upperBound = MemoryLayout.size * 8 - 1 71 | return self[range.lowerBound ... upperBound] 72 | } 73 | set { 74 | let upperBound = MemoryLayout.size * 8 - 1 75 | self[range.lowerBound ... upperBound] = newValue 76 | } 77 | } 78 | } 79 | 80 | public extension BinaryInteger { 81 | @inlinable 82 | var bits: Bits { 83 | get { 84 | Bits(value: self) 85 | } 86 | set { 87 | self = newValue.value 88 | } 89 | } 90 | } 91 | 92 | public extension Bits { 93 | subscript(index: Int) -> T { 94 | get { 95 | self[index ... index] 96 | } 97 | set { 98 | self[index ... index] = newValue 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Sources/Everything/Memory/Memory.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MemoryLayout { 4 | /// is plain old data 5 | static var isPOD: Bool { 6 | _isPOD(T.self) 7 | } 8 | } 9 | 10 | public func unsafeCast(_ x: some Any, to _: U.Type) -> U { 11 | // swiftlint:disable:next force_cast 12 | x as! U 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Benchmark.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func benchmark(closure: () -> Void) -> TimeInterval { 4 | let start = mach_absolute_time() 5 | closure() 6 | let end = mach_absolute_time() 7 | 8 | var info = mach_timebase_info_data_t() 9 | if mach_timebase_info(&info) != 0 { 10 | unimplemented() 11 | } 12 | let nanos = (end - start) * UInt64(info.numer) / UInt64(info.denom) 13 | return TimeInterval(nanos) / TimeInterval(NSEC_PER_SEC) 14 | } 15 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/BinaryCoding.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct BinaryEncoder { 4 | public init() { 5 | } 6 | 7 | public func encode(_ value: some Encodable, into writer: OutputStream) throws { 8 | let encoder = BinaryEncoder_(writer: writer) 9 | try value.encode(to: encoder) 10 | } 11 | 12 | // swiftlint:disable:next type_name 13 | struct BinaryEncoder_: Encoder { 14 | var codingPath: [CodingKey] = [] 15 | 16 | var userInfo: [CodingUserInfoKey: Any] = [:] 17 | 18 | var writer: OutputStream 19 | 20 | func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key: CodingKey { 21 | KeyedEncodingContainer(KeyedEncodingContainer_(writer: writer)) 22 | } 23 | 24 | func unkeyedContainer() -> UnkeyedEncodingContainer { 25 | unimplemented() 26 | } 27 | 28 | func singleValueContainer() -> SingleValueEncodingContainer { 29 | unimplemented() 30 | } 31 | 32 | // swiftlint:disable:next type_name 33 | struct KeyedEncodingContainer_: KeyedEncodingContainerProtocol where Key: CodingKey { 34 | var codingPath: [CodingKey] = [] 35 | var writer: OutputStream 36 | 37 | mutating func encodeNil(forKey key: Key) throws { 38 | unimplemented() 39 | } 40 | 41 | mutating func encode(_ value: Bool, forKey key: Key) throws { 42 | try writer.write(value) 43 | } 44 | 45 | mutating func encode(_ value: String, forKey key: Key) throws { 46 | try writer.write(value) 47 | } 48 | 49 | mutating func encode(_ value: Double, forKey key: Key) throws { 50 | try writer.write(value) 51 | } 52 | 53 | mutating func encode(_ value: Float, forKey key: Key) throws { 54 | try writer.write(value) 55 | } 56 | 57 | mutating func encode(_ value: Int, forKey key: Key) throws { 58 | try writer.write(value) 59 | } 60 | 61 | mutating func encode(_ value: Int8, forKey key: Key) throws { 62 | try writer.write(value) 63 | } 64 | 65 | mutating func encode(_ value: Int16, forKey key: Key) throws { 66 | try writer.write(value) 67 | } 68 | 69 | mutating func encode(_ value: Int32, forKey key: Key) throws { 70 | try writer.write(value) 71 | } 72 | 73 | mutating func encode(_ value: Int64, forKey key: Key) throws { 74 | try writer.write(value) 75 | } 76 | 77 | mutating func encode(_ value: UInt, forKey key: Key) throws { 78 | try writer.write(value) 79 | } 80 | 81 | mutating func encode(_ value: UInt8, forKey key: Key) throws { 82 | try writer.write(value) 83 | } 84 | 85 | mutating func encode(_ value: UInt16, forKey key: Key) throws { 86 | try writer.write(value) 87 | } 88 | 89 | mutating func encode(_ value: UInt32, forKey key: Key) throws { 90 | try writer.write(value) 91 | } 92 | 93 | mutating func encode(_ value: UInt64, forKey key: Key) throws { 94 | try writer.write(value) 95 | } 96 | 97 | mutating func encode(_ value: some Encodable, forKey key: Key) throws { 98 | try writer.write(value) 99 | } 100 | 101 | mutating func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer where NestedKey: CodingKey { 102 | unimplemented() 103 | } 104 | 105 | mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { 106 | unimplemented() 107 | } 108 | 109 | mutating func superEncoder() -> Encoder { 110 | unimplemented() 111 | } 112 | 113 | mutating func superEncoder(forKey key: Key) -> Encoder { 114 | unimplemented() 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Box.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class Box { 4 | public let value: Element 5 | public init(_ value: Element) { 6 | self.value = value 7 | } 8 | } 9 | 10 | public extension Box { 11 | // Stolen from https://github.com/robrix/Box/blob/master/Box/Box.swift 12 | func map(_ transform: (Element) -> U) -> Box { 13 | Box(transform(value)) 14 | } 15 | } 16 | 17 | extension Box: CustomStringConvertible { 18 | public var description: String { 19 | String(describing: value) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/CompositeHash.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct CompositeHash: Hashable where Element: Hashable { 4 | let elements: [Element] 5 | 6 | public init(_ elements: [Element]) { 7 | self.elements = elements 8 | } 9 | } 10 | 11 | extension CompositeHash: Sendable where Element: Sendable { 12 | } 13 | 14 | extension CompositeHash: Codable where Element: Codable { 15 | public init(from decoder: Decoder) throws { 16 | let container = try decoder.singleValueContainer() 17 | elements = try container.decode([Element].self) 18 | } 19 | 20 | public func encode(to encoder: Encoder) throws { 21 | var container = encoder.singleValueContainer() 22 | try container.encode(elements) 23 | } 24 | } 25 | 26 | extension CompositeHash: Comparable where Element: Comparable { 27 | public static func < (lhs: Self, rhs: Self) -> Bool { 28 | let max = max(lhs.elements.count, rhs.elements.count) 29 | let lhs = lhs.elements.extended(count: max) 30 | let rhs = rhs.elements.extended(count: max) 31 | for (lhs, rhs) in zip(lhs, rhs) { 32 | switch (lhs, rhs) { 33 | case (.none, .none): 34 | fatalError("Should be impossible to be get here.") 35 | 36 | case (.some, .none): 37 | return false 38 | 39 | case (.none, .some): 40 | return true 41 | 42 | case (.some(let lhs), .some(let rhs)): 43 | if lhs < rhs { 44 | return true 45 | } 46 | if lhs > rhs { 47 | return false 48 | } 49 | continue 50 | } 51 | } 52 | return false 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/CustomTupleConvertable.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol Custom2TupleConvertable { 4 | associatedtype Element 5 | typealias Tuple = (Element, Element) 6 | 7 | init(tuple: Tuple) 8 | var tuple: Tuple { get } 9 | } 10 | 11 | public extension Custom2TupleConvertable { 12 | func map(_ transform: (Element) -> Element) -> Self { 13 | Self(tuple: (transform(tuple.0), transform(tuple.1))) 14 | } 15 | } 16 | 17 | public func floor(_ value: T) -> T where T: Custom2TupleConvertable, T.Element: FloatingPoint { 18 | value.map(floor) 19 | } 20 | 21 | public func ceil(_ value: T) -> T where T: Custom2TupleConvertable, T.Element: FloatingPoint { 22 | value.map(ceil) 23 | } 24 | 25 | public func round(_ value: T) -> T where T: Custom2TupleConvertable, T.Element: FloatingPoint { 26 | value.map(round) 27 | } 28 | 29 | public func min(_ lhs: T, _ rhs: T) -> T where T: Custom2TupleConvertable, T.Element: Comparable { 30 | let lhs = lhs.tuple 31 | let rhs = rhs.tuple 32 | return T(tuple: (min(lhs.0, rhs.0), y: min(lhs.1, rhs.1))) 33 | } 34 | 35 | public func max(_ lhs: T, _ rhs: T) -> T where T: Custom2TupleConvertable, T.Element: Comparable { 36 | let lhs = lhs.tuple 37 | let rhs = rhs.tuple 38 | return T(tuple: (max(lhs.0, rhs.0), y: max(lhs.1, rhs.1))) 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Errno.swift: -------------------------------------------------------------------------------- 1 | import Darwin 2 | import Foundation 3 | 4 | public extension POSIXError { 5 | static func errno(userInfo: [String: Any] = [:]) -> POSIXError? { 6 | guard let code = POSIXErrorCode(rawValue: Darwin.errno) else { 7 | return nil 8 | } 9 | return POSIXError(code, userInfo: userInfo) 10 | } 11 | 12 | init?(_ code: Int32, userInfo: [String: Any] = [:]) { 13 | guard let code = POSIXErrorCode(rawValue: code) else { 14 | return nil 15 | } 16 | self = POSIXError(code, userInfo: userInfo) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Hashing.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | internal extension Int { 4 | static func addIgnoringOverflow(_ lhs: Int, _ rhs: Int) -> Int { 5 | lhs.addingReportingOverflow(rhs).0 6 | } 7 | } 8 | 9 | public func hash_combine(_ lhs: Int, _ rhs: Int) -> Int { 10 | // 0x9e3779b9 11 | // http://stackoverflow.com/questions/5889238/why-is-xor-the-default-way-to-combine-hashes#5889254 12 | let seed = 0x9E3_779B_97F4_A7C1 13 | 14 | // return lhs ^ rhs + seed + (lhs << 6) + (lhs >> 2) 15 | return lhs ^ Int.addIgnoringOverflow(Int.addIgnoringOverflow(rhs, seed), Int.addIgnoringOverflow(lhs << 6, lhs >> 2)) 16 | } 17 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Identified.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // This is useful for putting objects in sets that are either not hashable or have multiple possible keys 4 | public struct Identified: Identifiable, Hashable { 5 | public let id: ID 6 | public let value: Value 7 | 8 | public init(id: ID, value: Value) { 9 | self.id = id 10 | self.value = value 11 | } 12 | 13 | public init(id: KeyPath, value: Value) { 14 | self = Self(id: value[keyPath: id], value: value) 15 | } 16 | 17 | public static func == (lhs: Self, rhs: Self) -> Bool { 18 | lhs.id == rhs.id 19 | } 20 | 21 | public func hash(into hasher: inout Hasher) { 22 | id.hash(into: &hasher) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Logging.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | import Foundation 3 | import os.log 4 | 5 | // https://developer.apple.com/documentation/os/logging/generating_log_messages_from_your_code 6 | 7 | public extension Error { 8 | func log(level: OSLogType = .error, file: String = #file, line: Int = #line, column: Int = #column, function: String = #function, dsohandle: UnsafeRawPointer = #dsohandle) { 9 | let logger = Logger() 10 | logger.log(level: level, "\(String(describing: self))") 11 | } 12 | } 13 | 14 | public func warning(_ message: @autoclosure () -> String? = Optional.none, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) { 15 | warning(false, message(), file: file, function: function, line: line) 16 | } 17 | 18 | public func warning(_ closure: @autoclosure () -> Bool = false, _ message: @autoclosure () -> String? = Optional.none, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) { 19 | guard closure() == false else { 20 | return 21 | } 22 | 23 | let logger = Logger() 24 | if let message = message() { 25 | logger.debug("\(message)") 26 | } else { 27 | logger.debug("Warning! \(file)#\(line)") 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/LolUID.swift: -------------------------------------------------------------------------------- 1 | import os.log 2 | 3 | @available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) 4 | @available(*, deprecated, message: "Use TrivialID") 5 | public struct LolUID: Hashable { 6 | static let lock = OSAllocatedUnfairLock(uncheckedState: 0) 7 | 8 | static func nextID() -> Int { 9 | lock.withLock { nextID in 10 | let id = nextID 11 | nextID += 1 12 | return id 13 | } 14 | } 15 | 16 | public let id: Int 17 | 18 | public init() { 19 | id = Self.nextID() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/MachTime.swift: -------------------------------------------------------------------------------- 1 | import CoreVideo 2 | import Foundation 3 | 4 | public extension CVTimeStamp { 5 | var seconds: TimeInterval { 6 | TimeInterval(videoTime) * TimeInterval(videoTimeScale) 7 | } 8 | } 9 | 10 | public class MachTime { 11 | public var timebase = mach_timebase_info_data_t() 12 | 13 | public init() { 14 | if mach_timebase_info(&timebase) != 0 { 15 | unimplemented() 16 | } 17 | } 18 | 19 | public func currentNanos() -> UInt64 { 20 | mach_absolute_time() * UInt64(timebase.numer) / UInt64(timebase.denom) 21 | } 22 | 23 | public func current() -> TimeInterval { 24 | TimeInterval(currentNanos()) / TimeInterval(NSEC_PER_SEC) 25 | } 26 | 27 | public func elapsed(_ f: () -> Void) -> TimeInterval { 28 | let start = currentNanos() 29 | f() 30 | let end = currentNanos() 31 | return TimeInterval(end - start) / TimeInterval(NSEC_PER_SEC) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Misc.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if os(macOS) 4 | public func makeRamDisk(size: UInt64, name: String) throws -> URL { 5 | let mountPoint = URL(fileURLWithPath: "/Volumes/\(name)") 6 | if FileManager().fileExists(atPath: mountPoint.path) { 7 | unimplemented() 8 | } 9 | let size = size / 512 10 | let device = try Process.checkOutputString(launchPath: "/usr/bin/hdiutil", arguments: shlex("attach -nomount ram://\(size)")).trimmingCharacters(in: .whitespaces) 11 | print(try Process.checkOutputString(launchPath: "/usr/sbin/diskutil", arguments: shlex("erasevolume HFS+ \(name) \(device)"))) 12 | if !FileManager().fileExists(atPath: mountPoint.path) { 13 | unimplemented() 14 | } 15 | return mountPoint 16 | } 17 | #endif 18 | 19 | public struct Platform: Hashable, Sendable { 20 | let rawValue: String 21 | public static let macOS = Self(rawValue: "macOS") 22 | public static let iOS = Self(rawValue: "iOS") 23 | public static let tvOS = Self(rawValue: "tvOS") 24 | public static let watchOS = Self(rawValue: "watchOS") 25 | public static let linux = Self(rawValue: "linux") 26 | 27 | #if os(macOS) 28 | public static let current = macOS 29 | #elseif os(iOS) || os(tvOS) 30 | public static let current = iOS 31 | #else 32 | public static let current: Platform = { 33 | fatalError("Unknown platform") 34 | }() 35 | #endif 36 | } 37 | 38 | public func cast(_ value: Any, as: T.Type) throws -> T { 39 | guard let value = value as? T else { 40 | throw GeneralError.valueConversionFailure 41 | } 42 | return value 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Named.swift: -------------------------------------------------------------------------------- 1 | public protocol Named { 2 | var name: String { get } 3 | } 4 | 5 | public extension Named where Self: Identifiable { 6 | var id: String { name } 7 | } 8 | 9 | public extension Array where Element: Named { 10 | subscript(name: String) -> Element? { 11 | first { $0.name == name } 12 | } 13 | } 14 | 15 | public extension Array where Element: Identifiable { 16 | subscript(id: Element.ID) -> Element? { 17 | first { $0.id == id } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/OutputStream.swift: -------------------------------------------------------------------------------- 1 | //// 2 | //// File 2.swift 3 | //// 4 | //// 5 | //// Created by Jonathan Wight on 4/6/20. 6 | //// 7 | // 8 | // import Foundation 9 | // 10 | // public protocol OutputStream { 11 | // mutating func write(bytes: T) throws where T: Collection, T.Element == UInt8 12 | // mutating func write(_ value: String) throws 13 | // mutating func write(_ value: T) throws 14 | // } 15 | // 16 | // public class BinaryOutputStream: OutputStream where Buffer: RangeReplaceableCollection, Buffer.Element == UInt8 { 17 | // public private(set) var buffer: Buffer 18 | // 19 | // public enum StringEncodingStrategy { 20 | // case undecorated 21 | // case nilTerminated 22 | // case lengthPrefixed 23 | // case custom((BinaryOutputStream, String) throws -> Void) 24 | // } 25 | // 26 | // public var stringEncodingStrategy: StringEncodingStrategy = .undecorated 27 | // public var stringEncoding: String.Encoding = .utf8 28 | // public var allowLossyStringConversion: Bool = false 29 | // 30 | // var current: Buffer.Index 31 | // 32 | // public init(buffer: Buffer) { 33 | // self.buffer = buffer 34 | // current = buffer.startIndex 35 | // } 36 | // 37 | // public func write(bytes: T) throws where T: Collection, T.Element == UInt8 { 38 | // let end = buffer.index(current, offsetBy: bytes.count) 39 | // buffer.replaceSubrange(current ..< end, with: bytes) 40 | // current = end 41 | // } 42 | // 43 | // public func write(_ value: String) throws { 44 | // switch stringEncodingStrategy { 45 | // case .undecorated: 46 | // guard let data = value.data(using: stringEncoding, allowLossyConversion: allowLossyStringConversion) else { 47 | // fatalError() 48 | // } 49 | // try write(bytes: data) 50 | // case .nilTerminated: 51 | // guard let data = value.data(using: stringEncoding, allowLossyConversion: allowLossyStringConversion) else { 52 | // fatalError() 53 | // } 54 | // try write(bytes: data) 55 | // try write(bytes: [UInt8(0)]) 56 | // case .lengthPrefixed: 57 | // guard let data = value.data(using: stringEncoding, allowLossyConversion: allowLossyStringConversion) else { 58 | // fatalError() 59 | // } 60 | // guard data.count <= 255 else { 61 | // fatalError() 62 | // } 63 | // try write(bytes: [UInt8(data.count)]) 64 | // try write(bytes: data) 65 | // case .custom(let custom): 66 | // try custom(self, value) 67 | // } 68 | // } 69 | // 70 | // public func write(_ value: T) throws { 71 | // try withUnsafeBytes(of: value) { bytes in 72 | // try write(bytes: bytes) 73 | // } 74 | // } 75 | // } 76 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Random.swift: -------------------------------------------------------------------------------- 1 | // swiftlint:disable identifier_name 2 | 3 | import Foundation 4 | 5 | extension RandomNumberGenerator { 6 | static var max: UInt64 { 7 | UInt64.max 8 | } 9 | } 10 | 11 | public protocol ConstrainedRandomNumberGenerator: RandomNumberGenerator { 12 | static var max: UInt64 { get } 13 | } 14 | 15 | // MARK: - 16 | 17 | public extension RandomNumberGenerator { 18 | @available(*, deprecated, message: "UInt.random(in: 1...100). Code left in for reference.") 19 | mutating func random(uniform n: UInt64) -> UInt64 { 20 | // https://zuttobenkyou.wordpress.com/2012/10/18/generating-random-numbers-without-modulo-bias/ 21 | let rand_excess = (Self.max % n) + 1 22 | let rand_limit = Self.max - rand_excess 23 | var x: UInt64 24 | repeat { 25 | x = next() 26 | } 27 | while x > rand_limit 28 | return x % n 29 | } 30 | } 31 | 32 | // MARK: - 33 | 34 | // MARK: - 35 | 36 | public protocol RandomInRange where Self: Comparable { 37 | static func random(in: ClosedRange, using generator: inout R) -> Self where R: RandomNumberGenerator 38 | } 39 | 40 | extension Double: RandomInRange { 41 | } 42 | 43 | extension Float: RandomInRange { 44 | } 45 | 46 | extension Int: RandomInRange { 47 | } 48 | 49 | public extension Collection where Element: FloatingPoint & RandomInRange { 50 | func weightedRandomIndex(using generator: inout some RandomNumberGenerator) -> Index { 51 | let total = reduce(0, +) 52 | let cumulativeWeights = reduce(into: []) { accumulator, current in 53 | accumulator += [(accumulator.last ?? 0) + current] 54 | } 55 | let guess = Element.random(in: 0 ... total, using: &generator) 56 | let result = cumulativeWeights.enumerated().first { _, weight in 57 | guess < weight 58 | } 59 | 60 | let offset = result?.offset ?? count - 1 61 | return index(startIndex, offsetBy: offset) 62 | } 63 | 64 | func weightedRandomIndex() -> Index { 65 | var rng = SystemRandomNumberGenerator() 66 | return weightedRandomIndex(using: &rng) 67 | } 68 | } 69 | 70 | // MARK: - 71 | 72 | // let s = UInt64(UInt(bitPattern: "hello world".strongHashValue)) 73 | // var r = SplitMix64() 74 | // print((0..<16).map({ _ in r.random(uniform:100) })) 75 | // let count = 1_000_000_000 76 | // var data = Data(count: MemoryLayout.size * count) 77 | // data.withUnsafeMutableBytes() { 78 | // (pointer: UnsafeMutablePointer ) in 79 | // 80 | // var pointer = pointer 81 | // 82 | // for _ in 0.. UInt64 { 98 | // swiftlint:disable:next legacy_random 99 | UInt64(arc4random()) 100 | } 101 | } 102 | 103 | // http://xoroshiro.di.unimi.it/xoroshiro128plus.c 104 | public class Xoroshiro128Plus: RandomNumberGenerator { 105 | public typealias State = (UInt64, UInt64) 106 | 107 | public var s: State // = (0xbeac0467eba5facb, 0xd86b048b86aa9922) 108 | 109 | public required init(s: State) { 110 | self.s = s 111 | } 112 | 113 | public func next() -> UInt64 { 114 | func rotl(_ x: UInt64, _ k: Int) -> UInt64 { 115 | (x << k) | (x >> (64 - k)) 116 | } 117 | let s0 = s.0 118 | var s1 = s.1 119 | let result = s0.addingReportingOverflow(s1).partialValue 120 | s1 ^= s0 121 | s.0 = rotl(s0, 55) ^ s1 ^ (s1 << 14) // a, b 122 | s.1 = rotl(s1, 36) // c 123 | return UInt64(result) 124 | } 125 | } 126 | 127 | public class SplitMix64: RandomNumberGenerator { 128 | // http://xorshift.di.unimi.it/splitmix64.c 129 | 130 | public var s: UInt64 131 | 132 | public required init(s: UInt64) { 133 | self.s = s 134 | } 135 | 136 | public func next() -> UInt64 { 137 | s = s &+ 0x9E37_79B9_7F4A_7C15 138 | var z = s 139 | z = (z ^ (z >> 30)) &* 0xBF58_476D_1CE4_E5B9 140 | z = (z ^ (z >> 27)) &* 0x94D0_49BB_1331_11EB 141 | return UInt64(z ^ (z >> 31)) 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Tagged+Radians.swift: -------------------------------------------------------------------------------- 1 | public enum RadiansTag {} 2 | 3 | public typealias Radians = Tagged 4 | 5 | // MARK: - 6 | 7 | public enum DegreesTag {} 8 | 9 | public typealias Degrees = Tagged 10 | 11 | // MARK: - 12 | 13 | public extension Tagged where Kind == RadiansTag, Value: BinaryFloatingPoint { 14 | var degrees: Degrees { 15 | Degrees(rawValue: rawValue * 180 / .pi) 16 | } 17 | } 18 | 19 | public extension Tagged where Kind == DegreesTag, Value: BinaryFloatingPoint { 20 | var radians: Radians { 21 | Radians(rawValue: rawValue * .pi / 180) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/Timestamp.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | * A wrapper around CFAbsoluteTime 5 | * 6 | * CFAbsoluteTime is just typealias for a Double. By wrapping it in a struct we're able to extend it. 7 | */ 8 | public struct Timestamp { 9 | public let absoluteTime: CFAbsoluteTime 10 | 11 | public init() { 12 | absoluteTime = CFAbsoluteTimeGetCurrent() 13 | } 14 | 15 | public init(absoluteTime: CFAbsoluteTime) { 16 | self.absoluteTime = absoluteTime 17 | } 18 | } 19 | 20 | // MARK: - 21 | 22 | extension Timestamp: Equatable { 23 | public static func == (lhs: Timestamp, rhs: Timestamp) -> Bool { 24 | lhs.absoluteTime == rhs.absoluteTime 25 | } 26 | } 27 | 28 | // MARK: - 29 | 30 | extension Timestamp: Comparable { 31 | public static func < (lhs: Timestamp, rhs: Timestamp) -> Bool { 32 | lhs.absoluteTime < rhs.absoluteTime 33 | } 34 | } 35 | 36 | // MARK: - 37 | 38 | extension Timestamp: Hashable { 39 | public func hash(into hasher: inout Hasher) { 40 | absoluteTime.hash(into: &hasher) 41 | } 42 | } 43 | 44 | // MARK: - 45 | 46 | extension Timestamp: CustomStringConvertible { 47 | public var description: String { 48 | String(absoluteTime) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/Everything/Misc/TrivialID.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrivialID.swift 3 | // CacheTest 4 | // 5 | // Created by Jonathan Wight on 5/10/24. 6 | // 7 | 8 | import Foundation 9 | import os 10 | 11 | public struct TrivialID: Sendable, Hashable { 12 | struct StaticState { 13 | var scopesByName: [String: Scope] = [:] 14 | var nextSerials: [Scope: Int] = [:] 15 | } 16 | 17 | static let staticState: OSAllocatedUnfairLock = .init(initialState: .init()) 18 | 19 | struct Scope: Hashable { 20 | var name: String 21 | var token: Int 22 | 23 | init(name: String, token: Int = .random(in: 0...0xFFFFFF)) { 24 | self.name = name 25 | self.token = token 26 | } 27 | } 28 | 29 | static func scope(for name: String) -> Scope { 30 | Self.staticState.withLock { staticState in 31 | let scope = staticState.scopesByName[name, default: .init(name: name)] 32 | staticState.scopesByName[name] = scope 33 | return scope 34 | } 35 | } 36 | 37 | var scope: Scope 38 | var serial: Int 39 | 40 | private init(scope: Scope, serial: Int) { 41 | self.scope = scope 42 | self.serial = serial 43 | } 44 | 45 | public init(scope name: String = "") { 46 | self = Self.staticState.withLock { staticState in 47 | let scope = staticState.scopesByName[name, default: .init(name: name)] 48 | let serial = staticState.nextSerials[scope, default: 0] + 1 49 | staticState.scopesByName[name] = scope 50 | staticState.nextSerials[scope] = serial 51 | return .init(scope: scope, serial: serial) 52 | } 53 | } 54 | 55 | public static func dump() { 56 | staticState.withLock { staticState in 57 | debugPrint(staticState) 58 | } 59 | } 60 | } 61 | 62 | extension TrivialID: CustomStringConvertible { 63 | public var description: String { 64 | if scope.name.isEmpty { 65 | return "#\(serial)" 66 | } 67 | return "\(scope.name):#\(serial)" 68 | } 69 | } 70 | 71 | extension TrivialID: CustomDebugStringConvertible { 72 | public var debugDescription: String { 73 | "TrivialID(scope: \(scope), serial: \(serial))" 74 | } 75 | } 76 | 77 | /// Decoding a TrivialID is potentially a bad idea and can lead to ID conflicts if IDs have already been generated using the same scope. 78 | extension TrivialID: Codable { 79 | public init(from decoder: any Decoder) throws { 80 | let container = try decoder.singleValueContainer() 81 | let string = try container.decode(String.self) 82 | let pattern = #/^(?.+)\.(?.+):(?\d+)$/# 83 | guard let match = string.wholeMatch(of: pattern) else { 84 | fatalError() 85 | } 86 | guard let scopeToken = Int(match.output.scopeToken, radix: 16) else { 87 | fatalError() 88 | } 89 | guard let serial = Int(match.output.serial) else { 90 | fatalError() 91 | } 92 | let scope = Scope(name: String(match.output.scopeName), token: scopeToken) 93 | TrivialID.staticState.withLock { staticState in 94 | if staticState.scopesByName[scope.name] == nil { 95 | staticState.scopesByName[scope.name] = scope 96 | } 97 | staticState.nextSerials[scope] = max(staticState.nextSerials[scope, default: 0], serial) 98 | } 99 | self = .init(scope: scope, serial: serial) 100 | } 101 | 102 | public func encode(to encoder: any Encoder) throws { 103 | var container = encoder.singleValueContainer() 104 | try container.encode("\(scope.name).\(String(scope.token, radix: 16)):\(serial)") 105 | } 106 | } 107 | 108 | extension TrivialID.Scope: CustomDebugStringConvertible { 109 | var debugDescription: String { 110 | "\(name).\(String(token, radix: 16))" 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Sources/Everything/Parsing/YACharacterSet.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct YACharacterSet: Sendable { 4 | public let set: Set 5 | 6 | public init(_ set: Set) { 7 | self.set = set 8 | } 9 | 10 | public init(_ characters: [Character]) { 11 | set = Set(characters) 12 | } 13 | 14 | public init(charactersIn string: String) { 15 | set = Set(string) 16 | } 17 | 18 | public func contains(_ member: Character) -> Bool { 19 | set.contains(member) 20 | } 21 | 22 | public static let asciiWhitespaces = Self(charactersIn: " \t\n\r") 23 | public static let whitespaces = asciiWhitespaces 24 | 25 | public static let decimalDigits = Self(charactersIn: "0123456789") 26 | } 27 | 28 | extension YACharacterSet { 29 | static func + (lhs: YACharacterSet, rhs: YACharacterSet) -> YACharacterSet { 30 | YACharacterSet(lhs.set.union(rhs.set)) 31 | } 32 | } 33 | 34 | // public class func controlCharacterSet() -> NSCharacterSet 35 | // public class func whitespaceCharacterSet() -> NSCharacterSet 36 | // public class func whitespaceAndNewlineCharacterSet() -> NSCharacterSet 37 | // public class func decimalDigitCharacterSet() -> NSCharacterSet 38 | // public class func letterCharacterSet() -> NSCharacterSet 39 | // public class func lowercaseLetterCharacterSet() -> NSCharacterSet 40 | // public class func uppercaseLetterCharacterSet() -> NSCharacterSet 41 | // public class func nonBaseCharacterSet() -> NSCharacterSet 42 | // public class func alphanumericCharacterSet() -> NSCharacterSet 43 | // public class func decomposableCharacterSet() -> NSCharacterSet 44 | // public class func illegalCharacterSet() -> NSCharacterSet 45 | // public class func punctuationCharacterSet() -> NSCharacterSet 46 | // public class func capitalizedLetterCharacterSet() -> NSCharacterSet 47 | // public class func symbolCharacterSet() -> NSCharacterSet 48 | // @available(OSX 10.5, *) 49 | // public class func newlineCharacterSet() -> NSCharacterSet 50 | -------------------------------------------------------------------------------- /Sources/Everything/PropertyWrappers/PropertyWrappers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @propertyWrapper 4 | public struct Clamping { 5 | public var value: Value 6 | public let range: ClosedRange 7 | 8 | public init(initialValue value: Value, _ range: ClosedRange) { 9 | precondition(range.contains(value)) 10 | self.value = value 11 | self.range = range 12 | } 13 | 14 | public var wrappedValue: Value { 15 | get { value } 16 | set { value = min(max(range.lowerBound, newValue), range.upperBound) } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Everything/RadixedIntegerFormatStyle.swift: -------------------------------------------------------------------------------- 1 | // All removed. Use http://github.com/schwa/SwiftFormats 2 | -------------------------------------------------------------------------------- /Sources/Everything/Scratch/Scratch.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // MARK: - 4 | 5 | public struct WeakBox where Content: AnyObject { 6 | public weak var content: Content? 7 | 8 | public init(_ content: Content) { 9 | self.content = content 10 | } 11 | } 12 | 13 | // TODO: Move 14 | 15 | public extension UInt8 { 16 | init(character: Character) { 17 | assert(character.utf8.count == 1) 18 | self = character.utf8.first! 19 | } 20 | } 21 | 22 | public extension AsyncSequence { 23 | func cast (to: T.Type) -> AsyncCompactMapSequence { 24 | compactMap { $0 as? T } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/Binding+Extensions.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension Binding { 4 | func unsafeBinding() -> Binding where Value == V?, Value: Sendable { 5 | Binding { 6 | wrappedValue! 7 | } set: { 8 | wrappedValue = $0 9 | } 10 | } 11 | 12 | func unwrappingRebound(default: @escaping @Sendable () -> T) -> Binding where Value == T?, Value: Sendable { 13 | Binding(get: { 14 | self.wrappedValue ?? `default`() 15 | }, set: { 16 | self.wrappedValue = $0 17 | }) 18 | } 19 | 20 | // TODO: Rename 21 | func withUnsafeBinding(_ block: (Binding) throws -> R) rethrows -> R? where Value == V?, Value: Sendable { 22 | if wrappedValue != nil { 23 | return try block(Binding { wrappedValue! } set: { wrappedValue = $0 }) 24 | } 25 | return nil 26 | } 27 | } 28 | 29 | public extension Binding where Value == SwiftUI.Angle { 30 | init (radians: Binding) where F: BinaryFloatingPoint & Sendable { 31 | self = .init(get: { 32 | .radians(Double(radians.wrappedValue)) 33 | }, set: { 34 | radians.wrappedValue = F($0.radians) 35 | }) 36 | } 37 | } 38 | 39 | public extension Binding where Value == CGColor { 40 | init(simd: Binding>, colorSpace: CGColorSpace) { 41 | self = .init(get: { 42 | CGColor(colorSpace: colorSpace, components: [CGFloat(simd.wrappedValue[0]), CGFloat(simd.wrappedValue[1]), CGFloat(simd.wrappedValue[2])])! 43 | }, set: { newValue in 44 | let newValue = newValue.converted(to: colorSpace, intent: .defaultIntent, options: nil)! 45 | let components = newValue.components! 46 | simd.wrappedValue = SIMD3(Float(components[0]), Float(components[1]), Float(components[2])) 47 | }) 48 | } 49 | } 50 | 51 | public extension Binding where Value == Double { 52 | init (_ binding: Binding) where Other: BinaryFloatingPoint & Sendable { 53 | self.init { 54 | Double(binding.wrappedValue) 55 | } set: { newValue in 56 | binding.wrappedValue = Other(newValue) 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/Button+Extensions.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | // Button+Label conveniences 4 | public extension Button { 5 | init(title: LocalizedStringKey, image: String, action: @escaping () -> Void) where Label == SwiftUI.Label { 6 | self = Button(action: action) { 7 | Label(title, image: image) 8 | } 9 | } 10 | 11 | init(title: LocalizedStringKey, systemImage: String, action: @escaping () -> Void) where Label == SwiftUI.Label { 12 | self = Button(action: action) { 13 | Label(title, systemImage: systemImage) 14 | } 15 | } 16 | } 17 | 18 | // SF Symbol conveniences 19 | public extension Button { 20 | init(systemImage systemName: String, action: @escaping () -> Void) where Label == Image { 21 | self = Button(action: action) { 22 | Image(systemName: systemName) 23 | } 24 | } 25 | 26 | init(title: String, systemImage systemName: String, action: @escaping @Sendable () async -> Void) where Label == SwiftUI.Label { 27 | self = Button(action: { 28 | Task { 29 | await action() 30 | } 31 | }, label: { 32 | SwiftUI.Label(title, systemImage: systemName) 33 | }) 34 | } 35 | } 36 | 37 | // Async extensions 38 | public extension Button { 39 | init(_ title: String, action: @escaping @Sendable () async -> Void) where Label == Text { 40 | self = Button(title) { 41 | Task { 42 | await action() 43 | } 44 | } 45 | } 46 | 47 | init(systemImage systemName: String, action: @escaping @Sendable () async -> Void) where Label == Image { 48 | self = Button(action: { 49 | Task { 50 | await action() 51 | } 52 | }, label: { 53 | Image(systemName: systemName) 54 | }) 55 | } 56 | 57 | init(action: @Sendable @escaping () async -> Void, @ViewBuilder label: () -> Label) { 58 | self = Button(action: { 59 | Task { 60 | await action() 61 | } 62 | }, label: { 63 | label() 64 | }) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/Image+Extensions.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension Image { 4 | init(data: Data) throws { 5 | #if os(macOS) 6 | guard let nsImage = NSImage(data: data) else { 7 | throw GeneralError.generic("Could not load image") 8 | } 9 | self = Image(nsImage: nsImage) 10 | #else 11 | guard let uiImage = UIImage(data: data) else { 12 | throw GeneralError.generic("Could not load image") 13 | } 14 | self = Image(uiImage: uiImage) 15 | #endif 16 | } 17 | } 18 | 19 | public extension Image { 20 | init(url: URL) throws { 21 | #if os(macOS) 22 | guard let nsImage = NSImage(contentsOf: url) else { 23 | throw GeneralError.generic("Could not load image") 24 | } 25 | self = Image(nsImage: nsImage) 26 | #else 27 | guard let uiImage = UIImage(contentsOfFile: url.path) else { 28 | throw GeneralError.generic("Could not load image") 29 | } 30 | self = Image(uiImage: uiImage) 31 | #endif 32 | } 33 | } 34 | 35 | public extension Image { 36 | init(cgImage: CGImage) { 37 | #if os(macOS) 38 | let nsImage = NSImage(cgImage: cgImage, size: CGSize(width: cgImage.width, height: cgImage.height)) 39 | self = Image(nsImage: nsImage) 40 | #else 41 | let uiImage = UIImage(cgImage: cgImage) 42 | self = Image(uiImage: uiImage) 43 | #endif 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/InigoColorPalette.swift: -------------------------------------------------------------------------------- 1 | import simd 2 | import SwiftUI 3 | 4 | public extension Color { 5 | func legibleComplement() -> Color? { 6 | guard let cgColor else { 7 | return nil 8 | } 9 | guard let converted = cgColor.converted(to: CGColorSpace(name: CGColorSpace.linearSRGB)!, intent: .defaultIntent, options: nil) else { 10 | fatalError("Could not convert color to colorspace") 11 | } 12 | let components = converted.components! 13 | let r = components[0] 14 | let g = components[1] 15 | let b = components[2] 16 | let brightness = r * 0.299 + g * 0.587 + b * 0.114 17 | if brightness < 0.5 { 18 | return Color.white 19 | } 20 | return Color.black 21 | } 22 | } 23 | 24 | public extension Color { 25 | init(_ v: SIMD3) { 26 | self = Color(.displayP3, red: v.x, green: v.y, blue: v.z, opacity: 1.0) 27 | } 28 | } 29 | 30 | // https://iquilezles.org/www/articles/palettes/palettes.htm 31 | public struct InigoColourPalette: Sendable { 32 | init(_ a: SIMD3, _ b: SIMD3, _ c: SIMD3, _ d: SIMD3) { 33 | self.a = a 34 | self.b = b 35 | self.c = c 36 | self.d = d 37 | } 38 | 39 | let a: SIMD3 40 | let b: SIMD3 41 | let c: SIMD3 42 | let d: SIMD3 43 | 44 | func color(at t: Double) -> SIMD3 { 45 | a + b * cos(.pi * 2 * (c * t + d)) 46 | } 47 | 48 | static let example1 = Self([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.33, 0.67]) 49 | static let example2 = Self([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.00, 0.10, 0.20]) 50 | static let example3 = Self([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.30, 0.20, 0.20]) 51 | static let example4 = Self([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.80, 0.90, 0.30]) 52 | static let example5 = Self([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.00, 0.15, 0.20]) 53 | static let example6 = Self([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.50, 0.20, 0.25]) 54 | static let example7 = Self([0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.00, 0.25, 0.25]) 55 | static let allExamples: [Self] = [.example1, .example2, .example3, .example4, .example5, .example6, .example7] 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/Styles.swift.gyb: -------------------------------------------------------------------------------- 1 | %{ 2 | from collections import namedtuple 3 | Style = namedtuple('Style', ['name', 'availability', 'unavailable']) 4 | styles = [ 5 | Style(name='ButtonStyle', availability=['macOS 10.15', 'iOS 13.0'], unavailable=[]), 6 | Style(name='ControlGroupStyle', availability=['macOS 10.15', 'iOS 13.0', 'tvOS 17.0'], unavailable=[]), 7 | Style(name='DatePickerStyle', availability=['macOS 13', 'iOS 16.0'], unavailable=['tvOS']), 8 | Style(name='DisclosureGroupStyle', availability=['macOS 13', 'iOS 16.0'], unavailable=['tvOS']), 9 | Style(name='FormStyle', availability=['macOS 13', 'iOS 16.0'], unavailable=[]), 10 | Style(name='GaugeStyle', availability=['macOS 13', 'iOS 16.0'], unavailable=['tvOS']), 11 | Style(name='GroupBoxStyle', availability=['macOS 10.15', 'iOS 13.0'], unavailable=['tvOS']), 12 | Style(name='LabelStyle', availability=['macOS 10.15', 'iOS 13.0'], unavailable=[]), 13 | Style(name='LabeledContentStyle', availability=['macOS 13', 'iOS 16.0'], unavailable=[]), 14 | # Style(name='ListStyle', availability='?', unavailable=[]), 15 | # Style(name='MenuBarExtraStyle', availability='?', unavailable=[]), 16 | # Style(name='MenuButtonStyle', availability='?', unavailable=[]), 17 | Style(name='MenuStyle', availability=['macOS 10.15', 'iOS 13.0', 'tvOS 17.0'], unavailable=[]), 18 | Style(name='NavigationSplitViewStyle', availability=['macOS 13', 'iOS 16.0'], unavailable=[]), 19 | # Style(name='PickerStyle', availability='?', unavailable=[]), 20 | # Style(name='PrimitiveButtonStyle', availability='?', unavailable=[]), 21 | Style(name='ProgressViewStyle', availability=['macOS 10.15', 'iOS 13.0'], unavailable=[]), 22 | # Style(name='ShapeStyle', availability='?', unavailable=[]), 23 | # Style(name='TabViewStyle', availability='?', unavailable=[]), 24 | Style(name='TableStyle', availability=['macOS 12', 'iOS 16.0'], unavailable=['tvOS']), 25 | # Style(name='TextFieldStyle', availability='?', unavailable=[]), 26 | Style(name='ToggleStyle', availability=['macOS 10.15', 'iOS 13.0'], unavailable=[]), 27 | # Style(name='WindowStyle', availability='?', unavailable=[]), 28 | # Style(name='WindowToolbarStyle', availability='?', unavailable=[]), 29 | ] 30 | 31 | def lower(name): 32 | return name[0].lower() + name[1:] 33 | }% 34 | 35 | import SwiftUI 36 | 37 | % for style in styles: 38 | 39 | /// A type-erased `${style.name}`. 40 | /// 41 | /// Allows creation of type-erased `${style.name}` using a closure to create the style's body. 42 | % for availability in style.availability: 43 | @available(${availability}, *) 44 | % end 45 | % for unavailable in style.unavailable: 46 | @available(${unavailable}, unavailable) 47 | % end 48 | public struct Any${style.name} : ${style.name} where Body: View { 49 | let body: (Configuration) -> Body 50 | 51 | public init(_ body: @escaping (Configuration) -> Body) { 52 | self.body = body 53 | } 54 | 55 | public func makeBody(configuration: Configuration) -> some View { 56 | body(configuration) 57 | } 58 | } 59 | 60 | % for availability in style.availability: 61 | @available(${availability}, *) 62 | % end 63 | % for unavailable in style.unavailable: 64 | @available(${unavailable}, unavailable) 65 | % end 66 | public extension View { 67 | /// Modify the `${lower(style.name)}` style via a closure. 68 | func ${lower(style.name)}(_ body: @escaping (Any${style.name}.Configuration) -> B) -> some View where B: View { 69 | ${lower(style.name)}(Any${style.name}(body)) 70 | } 71 | } 72 | 73 | // MARK: - 74 | 75 | % end 76 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/SwiftUI+Extensions.swift: -------------------------------------------------------------------------------- 1 | // swiftlint:disable file_length 2 | 3 | import Combine 4 | import SwiftUI 5 | 6 | public extension View { 7 | func eraseToAnyView() -> AnyView { 8 | AnyView(self) 9 | } 10 | } 11 | 12 | /** 13 | Tired of sprinkling those little one shot `isPresenting` style state properties through your code? 14 | 15 | ValueView(value: false) { value in 16 | Button("Mass Follow") { 17 | value.wrappedValue = true 18 | } 19 | .fileImporter(isPresented: value, allowedContentTypes: [.commaSeparatedText]) { result in 20 | 21 | } 22 | } 23 | */ 24 | public struct ValueView: View where Content: View { 25 | @State 26 | private var value: Value 27 | let content: (Binding) -> Content 28 | 29 | public init(value: Value, @ViewBuilder content: @escaping (Binding) -> Content) { 30 | _value = State(wrappedValue: value) 31 | self.content = content 32 | } 33 | 34 | public var body: some View { 35 | content($value) 36 | } 37 | } 38 | 39 | public struct LazyView: View { 40 | let content: () -> Content 41 | public init(_ content: @escaping () -> Content) { 42 | self.content = content 43 | } 44 | 45 | public var body: Content { 46 | content() 47 | } 48 | } 49 | 50 | #if !os(tvOS) 51 | public struct PopoverButton: View where Label: View, Content: View { 52 | let label: () -> Label 53 | let content: () -> Content 54 | 55 | @State 56 | private var visible = false 57 | 58 | public init(label: @escaping () -> Label, content: @escaping () -> Content) { 59 | self.label = label 60 | self.content = content 61 | } 62 | 63 | public var body: some View { 64 | Button(action: { visible.toggle() }, label: label) 65 | .popover(isPresented: $visible, content: content) 66 | } 67 | } 68 | #endif 69 | 70 | public extension Gesture { 71 | func eraseToAnyGesture() -> AnyGesture { 72 | AnyGesture(self) 73 | } 74 | } 75 | 76 | public extension View { 77 | func gesture(_ gesture: () -> some Gesture) -> some View { 78 | self.gesture(gesture()) 79 | } 80 | } 81 | 82 | public extension View { 83 | func offset(_ point: CGPoint) -> some View { 84 | offset(x: point.x, y: point.y) 85 | } 86 | } 87 | 88 | public extension Text { 89 | init(describing value: Any) { 90 | self = Text(verbatim: "\(value)") 91 | } 92 | } 93 | 94 | public extension Text { 95 | static func lorem() -> Self { 96 | // swiftlint:disable line_length 97 | Text(""" 98 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 99 | """) 100 | // swiftlint:enable line_length 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Sources/Everything/SwiftUI/ViewAdapter.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | #if os(macOS) 4 | public struct ViewAdaptor: View where ViewType: NSView { 5 | let make: () -> ViewType 6 | let update: (ViewType) -> Void 7 | 8 | public init(make: @escaping () -> ViewType, update: @escaping (ViewType) -> Void) { 9 | self.make = make 10 | self.update = update 11 | } 12 | 13 | public var body: some View { 14 | Representation(make: make, update: update) 15 | } 16 | 17 | struct Representation: NSViewRepresentable { 18 | let make: () -> ViewType 19 | let update: (ViewType) -> Void 20 | 21 | func makeNSView(context: Context) -> ViewType { 22 | make() 23 | } 24 | 25 | func updateNSView(_ nsView: ViewType, context: Context) { 26 | update(nsView) 27 | } 28 | } 29 | } 30 | 31 | #elseif os(iOS) || os(tvOS) 32 | public struct ViewAdaptor: View where ViewType: UIView { 33 | let make: () -> ViewType 34 | let update: (ViewType) -> Void 35 | 36 | public init(make: @escaping () -> ViewType, update: @escaping (ViewType) -> Void) { 37 | self.make = make 38 | self.update = update 39 | } 40 | 41 | public var body: some View { 42 | Representation(make: make, update: update) 43 | } 44 | 45 | struct Representation: UIViewRepresentable { 46 | let make: () -> ViewType 47 | let update: (ViewType) -> Void 48 | 49 | func makeUIView(context: Context) -> ViewType { 50 | make() 51 | } 52 | 53 | func updateUIView(_ uiView: ViewType, context: Context) { 54 | update(uiView) 55 | } 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /Sources/EverythingUnsafeConformances/EverythingUnsafeConformances.swift: -------------------------------------------------------------------------------- 1 | import CoreGraphics 2 | import Foundation 3 | import MultipeerConnectivity 4 | 5 | extension CGImageAlphaInfo: @retroactive CustomStringConvertible { 6 | public var description: String { 7 | switch self { 8 | case .none: 9 | return "none" 10 | case .premultipliedLast: 11 | return "premultipliedLast" 12 | case .premultipliedFirst: 13 | return "premultipliedFirst" 14 | case .last: 15 | return "last" 16 | case .first: 17 | return "first" 18 | case .noneSkipLast: 19 | return "noneSkipLast" 20 | case .noneSkipFirst: 21 | return "noneSkipFirst" 22 | case .alphaOnly: 23 | return "alphaOnly" 24 | @unknown default: 25 | fatalError("Unknown case") 26 | } 27 | } 28 | } 29 | 30 | extension CGImageByteOrderInfo: @retroactive CustomStringConvertible { 31 | public var description: String { 32 | switch self { 33 | case .orderMask: 34 | return "orderMask" 35 | case .order16Little: 36 | return "order16Little" 37 | case .order32Little: 38 | return "order32Little" 39 | case .order16Big: 40 | return "order16Big" 41 | case .order32Big: 42 | return "order32Big" 43 | case .orderDefault: 44 | return "orderDefault" 45 | @unknown default: 46 | fatalError("Unknown case") 47 | } 48 | } 49 | } 50 | 51 | extension MCSessionState: @retroactive CustomStringConvertible { 52 | public var description: String { 53 | switch self { 54 | case .connected: 55 | return "connected" 56 | case .connecting: 57 | return "connecting" 58 | case .notConnected: 59 | return "notConnected" 60 | @unknown default: 61 | fatalError("Unknown case") 62 | } 63 | } 64 | } 65 | 66 | extension Character: Codable { 67 | public init(from decoder: Decoder) throws { 68 | let container = try decoder.singleValueContainer() 69 | let string = try container.decode(String.self) 70 | guard string.count == 1, let first = string.first else { 71 | fatalError("Unknown case") 72 | } 73 | self = first 74 | } 75 | 76 | public func encode(to encoder: Encoder) throws { 77 | var container = encoder.singleValueContainer() 78 | try container.encode(String(self)) 79 | } 80 | } 81 | 82 | extension CharacterSet: @retroactive ExpressibleByExtendedGraphemeClusterLiteral {} 83 | extension CharacterSet: @retroactive ExpressibleByUnicodeScalarLiteral {} 84 | extension CharacterSet: @retroactive ExpressibleByStringLiteral { 85 | public init(stringLiteral value: String) { 86 | self = CharacterSet(charactersIn: value) 87 | } 88 | } 89 | 90 | extension URL: @retroactive ExpressibleByExtendedGraphemeClusterLiteral {} 91 | extension URL: @retroactive ExpressibleByUnicodeScalarLiteral {} 92 | extension URL: @retroactive ExpressibleByStringLiteral { 93 | public init(stringLiteral value: String) { 94 | self.init(string: value)! 95 | } 96 | } 97 | 98 | extension URL: @retroactive ExpressibleByStringInterpolation { 99 | } 100 | -------------------------------------------------------------------------------- /TestPlans/Everything.xctestplan: -------------------------------------------------------------------------------- 1 | { 2 | "configurations" : [ 3 | { 4 | "id" : "F700882D-87D3-4579-B59E-4CE58F01BD3C", 5 | "name" : "Test Scheme Action", 6 | "options" : { 7 | 8 | } 9 | } 10 | ], 11 | "defaultOptions" : { 12 | 13 | }, 14 | "testTargets" : [ 15 | { 16 | "target" : { 17 | "containerPath" : "container:", 18 | "identifier" : "EverythingTests", 19 | "name" : "EverythingTests" 20 | } 21 | } 22 | ], 23 | "version" : 1 24 | } 25 | -------------------------------------------------------------------------------- /Tests/EverythingTests/BitRange_Tests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | class BitRangeTests: XCTestCase { 5 | func testScalarBitRange() { 6 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 0, count: 2, flipped: false), 0b11) 7 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 2, count: 2, flipped: false), 0b10) 8 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 4, count: 2, flipped: false), 0b01) 9 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 6, count: 2, flipped: false), 0b00) 10 | 11 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 0, count: 2, flipped: true), 0b00) 12 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 2, count: 2, flipped: true), 0b01) 13 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 4, count: 2, flipped: true), 0b10) 14 | XCTAssertEqual(bitRange(value: UInt8(0b0001_1011), start: 6, count: 2, flipped: true), 0b11) 15 | } 16 | 17 | func testScalarBitSet() { 18 | XCTAssertEqual(bitSet(value: UInt8(0b0001_1011), start: 0, count: 3, flipped: false, newValue: UInt8(0b100)), UInt8(0b0001_1100)) 19 | XCTAssertEqual(bitSet(value: UInt8(0b0001_1011), start: 2, count: 1, flipped: false, newValue: UInt8(0b1)), UInt8(0b0001_1111)) 20 | XCTAssertEqual(bitSet(value: UInt8(0b0001_1111), start: 0, count: 3, flipped: true, newValue: UInt8(0b111)), UInt8(0b1111_1111)) 21 | XCTAssertEqual(bitSet(value: UInt8(0b0000_0000), range: 5 ..< 8, flipped: true, newValue: UInt8(5)), UInt8(5)) 22 | } 23 | 24 | // TODO: 25 | // func testBufferRange1() { 26 | // 27 | // let tests: [(Int,Int,UIntMax)] = [ 28 | /// / (0, 1, 0x1), 29 | // (0, 4, 0x1111), 30 | // ] 31 | // 32 | // let count = 32 33 | // 34 | // for test in tests { 35 | // let result = buildBinary(count) { 36 | // (buffer) in 37 | // bitSet(buffer, start: test.0, count: test.1, newValue: test.2) 38 | // print(test.0, test.1) 39 | // } 40 | // 41 | // var bitString = BitString(count: count) 42 | // try! bitString.bitSet(test.0, count: test.1, newValue: test.2) 43 | // 44 | // XCTAssertEqual(bitString.string, try! byteArrayToBinary(result)) 45 | // } 46 | // } 47 | } 48 | -------------------------------------------------------------------------------- /Tests/EverythingTests/BitsTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | class Tests: XCTestCase { 5 | func testGetters() { 6 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[0 ... 7], 0xEF) 7 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[0 ..< 8], 0xEF) 8 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[...7], 0xEF) 9 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[..<8], 0xEF) 10 | 11 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[24 ... 31], 0xDE) 12 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[24 ..< 32], 0xDE) 13 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[24...], 0xDE) 14 | 15 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[8 ... 23], 0xADBE) 16 | XCTAssertEqual(UInt32(0xDEAD_BEEF).bits[8 ..< 24], 0xADBE) 17 | } 18 | 19 | func testSetters() { 20 | var value: UInt32 = 0xDEAD_BEEF 21 | 22 | value.bits[0 ... 7] = 0x12 23 | XCTAssertEqual(value, 0xDEAD_BE12) 24 | 25 | value = 0xDEAD_BEEF 26 | value.bits[0 ..< 8] = 0x12 27 | XCTAssertEqual(value, 0xDEAD_BE12) 28 | 29 | value = 0xDEAD_BEEF 30 | value.bits[...7] = 0x12 31 | XCTAssertEqual(value, 0xDEAD_BE12) 32 | 33 | value = 0xDEAD_BEEF 34 | value.bits[..<8] = 0x12 35 | XCTAssertEqual(value, 0xDEAD_BE12) 36 | 37 | value = 0xDEAD_BEEF 38 | value.bits[24 ... 31] = 0x12 39 | XCTAssertEqual(value, 0x12AD_BEEF) 40 | 41 | value = 0xDEAD_BEEF 42 | value.bits[24 ..< 32] = 0x12 43 | XCTAssertEqual(value, 0x12AD_BEEF) 44 | 45 | value = 0xDEAD_BEEF 46 | value.bits[24...] = 0x12 47 | XCTAssertEqual(value, 0x12AD_BEEF) 48 | 49 | value = 0xDEAD_BEEF 50 | value.bits[8 ... 23] = 0x1234 51 | XCTAssertEqual(value, 0xDE12_34EF) 52 | 53 | value = 0xDEAD_BEEF 54 | value.bits[8 ..< 24] = 0x1234 55 | XCTAssertEqual(value, 0xDE12_34EF) 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /Tests/EverythingTests/CSVTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | final class CSVTests: XCTestCase { 5 | func testCSVFieldsAll() { 6 | let items: [(String, String, [String])] = [ 7 | ("Test 1", "", []), 8 | ("Test 2", ",", ["", ""]), 9 | ("Test 3", "hello", ["hello"]), 10 | ("Test 4", "hello,world", ["hello", "world"]), 11 | ("Test 5", "hello,", ["hello", ""]), 12 | ("Test 6", ",hello", ["", "hello"]), 13 | ("Test 7", "\"hello\"", ["hello"]), 14 | ("Test 8", "\"hello\",world", ["hello", "world"]), 15 | ("Test 9", "hello,\"world\"", ["hello", "world"]), 16 | ("Test 10", "\"\"\"\"", ["\""]), 17 | ("Test 11", "\"Hello\"\"\"", ["Hello\""]), 18 | ("Test 12", "\"\"\"Hello\"", ["\"Hello"]), 19 | ] 20 | for (message, input, expectedOutput) in items { 21 | let output = CollectionScanner(elements: input).scan { $0.scanCSVFields() } 22 | XCTAssertEqual(output, expectedOutput, message) 23 | } 24 | } 25 | 26 | func testEmptyCSV() { 27 | let reader = CSVDictReader(data: "".data(using: .utf8)!) 28 | let rows = reader.makeIterator().collect() 29 | XCTAssertEqual(rows.count, 0) 30 | } 31 | 32 | func testCSV() { 33 | let content = #""" 34 | Fruit,Color 35 | "Apple",Green 36 | Banana,"Yellow" 37 | "Orange","Orange" 38 | """# 39 | 40 | let reader = CSVDictReader(data: content.data(using: .utf8)!, lineEndings: .LF) 41 | let rows = reader.makeIterator().collect() 42 | XCTAssertEqual(rows.count, 3) 43 | XCTAssertEqual(rows[0], ["Fruit": "Apple", "Color": "Green"]) 44 | XCTAssertEqual(rows[1], ["Fruit": "Banana", "Color": "Yellow"]) 45 | XCTAssertEqual(rows[2], ["Fruit": "Orange", "Color": "Orange"]) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Tests/EverythingTests/CollectionScannerTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | final class CollectionScannerTests: XCTestCase { 5 | func test() { 6 | var scanner = CollectionScanner(elements: "hello world") 7 | XCTAssertEqual(scanner.scan(count: 100), nil) 8 | XCTAssertEqual(scanner.atEnd, false) 9 | XCTAssertEqual(scanner.remainingCount, scanner.elements.count) 10 | XCTAssertEqual(scanner.remaining, "hello world") 11 | XCTAssertEqual(scanner.atEnd, false) 12 | XCTAssertEqual(scanner.scan(count: 0), "") 13 | XCTAssertEqual(scanner.scan(count: 5), "hello") 14 | XCTAssertEqual(scanner.atEnd, false) 15 | XCTAssertEqual(scanner.peek(), " ") 16 | XCTAssertEqual(scanner.scan(value: " "), true) 17 | XCTAssertEqual(scanner.atEnd, false) 18 | XCTAssertEqual(scanner.scan(value: Array("world!!!")), false) 19 | XCTAssertEqual(scanner.atEnd, false) 20 | XCTAssertEqual(scanner.scan(value: Array("WORLD")), false) 21 | XCTAssertEqual(scanner.atEnd, false) 22 | print(scanner.debugDescription) 23 | XCTAssertEqual(scanner.scan(value: Array("world")), true) 24 | XCTAssertEqual(scanner.atEnd, true) 25 | XCTAssertEqual(scanner.scan(count: 100), nil) 26 | XCTAssertEqual(scanner.scan(value: "X"), false) 27 | XCTAssertEqual(scanner.scan(value: ["X"]), false) 28 | XCTAssertEqual(scanner.remaining, "") 29 | XCTAssertEqual(scanner.remainingCount, 0) 30 | XCTAssertEqual(scanner.peek(), nil) 31 | XCTAssertEqual(scanner.peek(), nil) 32 | } 33 | 34 | func test2() { 35 | var scanner = CollectionScanner(elements: "hello world") 36 | XCTAssertEqual(scanner.current, scanner.elements.startIndex) 37 | XCTAssertEqual(scanner.scan(value: Array("XYZZY")), false) 38 | XCTAssertEqual(scanner.current, scanner.elements.startIndex) 39 | XCTAssertEqual(scanner.scan(value: Array("hello")), true) 40 | XCTAssertEqual(scanner.scan(value: " "), true) 41 | XCTAssertEqual(scanner.scan(value: Array("world")), true) 42 | XCTAssertEqual(scanner.atEnd, true) 43 | } 44 | 45 | func test3() { 46 | var scanner = CollectionScanner(elements: "a,b,c") 47 | XCTAssertEqual(scanner.scan(componentsSeparatedBy: ","), ["a", "b", "c"]) 48 | XCTAssertEqual(scanner.atEnd, true) 49 | XCTAssertEqual(scanner.scan(componentsSeparatedBy: ","), []) 50 | } 51 | 52 | func test4() { 53 | var scanner = CollectionScanner(elements: "a_b-c") 54 | XCTAssertEqual(scanner.scan(until: { "_-".contains($0) }), "a") 55 | XCTAssertEqual(scanner.scan(anyOf: Array("_-")), "_") 56 | XCTAssertEqual(scanner.scan(anyOf: Array("1234")), nil) 57 | XCTAssertEqual(scanner.scan(until: { "_-".contains($0) }), "b") 58 | XCTAssertEqual(scanner.scan(anyOf: Array("_-")), "-") 59 | XCTAssertEqual(scanner.scan(until: { "_-".contains($0) }), "c") 60 | XCTAssertEqual(scanner.atEnd, true) 61 | } 62 | 63 | func test5() { 64 | var scanner = CollectionScanner(elements: "a,b,") 65 | XCTAssertEqual(scanner.scanUpTo(value: ","), "a") 66 | XCTAssertEqual(scanner.scan(value: ","), true) 67 | XCTAssertEqual(scanner.scanUpTo(value: ","), "b") 68 | XCTAssertEqual(scanner.scan(value: ","), true) 69 | XCTAssertEqual(scanner.scanUpTo(value: ","), nil) 70 | XCTAssertEqual(scanner.atEnd, true) 71 | } 72 | 73 | func test6() { 74 | var scanner = CollectionScanner(elements: "a+++b+++") 75 | XCTAssertEqual(scanner.scanUpTo(value: Array("+++")), "a") 76 | XCTAssertEqual(scanner.scan(value: Array("+++")), true) 77 | XCTAssertEqual(scanner.scanUpTo(value: Array("+++")), "b") 78 | XCTAssertEqual(scanner.scan(value: Array("+++")), true) 79 | XCTAssertEqual(scanner.scanUpTo(value: Array("+++")), nil) 80 | XCTAssertEqual(scanner.atEnd, true) 81 | } 82 | 83 | func test7() { 84 | var scanner = CollectionScanner(elements: "a+++b++") 85 | XCTAssertEqual(scanner.scanUpTo(value: Array("+++")), "a") 86 | XCTAssertEqual(scanner.scan(value: Array("+++")), true) 87 | XCTAssertEqual(scanner.scanUpTo(value: Array("+++")), nil) 88 | XCTAssertEqual(scanner.atEnd, false) 89 | XCTAssertEqual(scanner.scan(value: Array("b++")), true) 90 | XCTAssertEqual(scanner.atEnd, true) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Tests/EverythingTests/CombineTests.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | @testable import Everything 3 | import XCTest 4 | 5 | class CombineTests: XCTestCase { 6 | func testExample() { 7 | XCTAssertEqual(Just(1).block(), 1) 8 | XCTAssertEqual(Just(1).block(), 1) 9 | 10 | XCTAssertEqual(Publishers.Sequence(sequence: [1, 2, 3]).block(), 3) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Tests/EverythingTests/ComparisonTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | class ComparisonTests: XCTestCase { 5 | func testExample() { 6 | XCTAssertEqual(compare(1, 1), Comparison.equal) 7 | XCTAssertEqual(compare(1, 2), Comparison.lesser) 8 | XCTAssertEqual(compare(2, 1), Comparison.greater) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Tests/EverythingTests/HeapTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import Foundation 3 | import XCTest 4 | 5 | class HeapTests: XCTestCase { 6 | func test1() { 7 | var heap = BinaryHeap(comparator: <) 8 | heap.push(100) 9 | XCTAssertEqual(heap.array, [100]) 10 | heap.push(200) 11 | XCTAssertEqual(heap.array, [100, 200]) 12 | XCTAssertEqual(heap.pop()!, 100) 13 | XCTAssertEqual(heap.pop()!, 200) 14 | } 15 | 16 | func test2() { 17 | var heap = BinaryHeap(comparator: <) 18 | heap.push(4) 19 | heap.push(7) 20 | heap.push(9) 21 | heap.push(0) 22 | heap.push(1) 23 | heap.push(0) 24 | XCTAssertEqual(heap.pop()!, 0) 25 | XCTAssertEqual(heap.pop()!, 0) 26 | XCTAssertEqual(heap.pop()!, 1) 27 | XCTAssertEqual(heap.pop()!, 4) 28 | XCTAssertEqual(heap.pop()!, 7) 29 | XCTAssertEqual(heap.pop()!, 9) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/EverythingTests/IdentifiableSetTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import Foundation 3 | import XCTest 4 | 5 | class IdentifiableSetTests: XCTestCase { 6 | struct S: Identifiable, ExpressibleByStringLiteral { 7 | let id: String 8 | init(stringLiteral value: String) { 9 | id = value 10 | } 11 | } 12 | 13 | func test1() { 14 | var set = IdentifiableSet() 15 | XCTAssert(set.isEmpty) 16 | XCTAssert(set.isEmpty) 17 | XCTAssert(!set.contains("A")) 18 | set.insert("A") 19 | XCTAssert(!set.isEmpty) 20 | XCTAssert(set.count == 1) 21 | XCTAssert(set.contains("A")) 22 | set.remove("A") 23 | XCTAssert(set.isEmpty) 24 | XCTAssert(set.isEmpty) 25 | XCTAssert(!set.contains("A")) 26 | } 27 | 28 | func test2() { 29 | let set = IdentifiableSet(["A", "B"]) 30 | XCTAssert(!set.isEmpty) 31 | XCTAssert(set.count == 2) 32 | XCTAssert(set.contains("A")) 33 | XCTAssert(set.contains("B")) 34 | XCTAssert(set.intersection(["A", "B"]).count == 2) 35 | XCTAssert(set.intersection(["C", "D"]).isEmpty) 36 | XCTAssert(set.intersection(["A", "C"]).count == 1) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Tests/EverythingTests/ParsingTests/CharacterSetTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | class CharacterSetTests: XCTestCase { 5 | func testExample() { 6 | let set = YACharacterSet.whitespaces 7 | 8 | XCTAssertTrue(set.contains(" ")) 9 | XCTAssertTrue(set.contains("\n")) 10 | XCTAssertTrue(set.contains("\r")) 11 | XCTAssertTrue(set.contains("\t")) 12 | 13 | XCTAssertFalse(set.contains("x")) 14 | XCTAssertFalse(set.contains("\\")) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Tests/EverythingTests/PathTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import Foundation 3 | import XCTest 4 | 5 | let githubActions = ProcessInfo.processInfo.environment["GITHUB_ACTIONS"] != nil 6 | 7 | class PathTests: XCTestCase { 8 | func testInit() { 9 | if githubActions { 10 | return 11 | } 12 | 13 | do { 14 | let path = FSPath("/tmp") 15 | XCTAssertEqual(path.path, "/tmp") 16 | } 17 | do { 18 | let path = FSPath(URL(fileURLWithPath: "/tmp")) 19 | XCTAssertEqual(path.path, "/tmp") 20 | } 21 | // do { 22 | // let path = FSPath(URL(string: "http://google.com")!) 23 | // XCTAssertNil(path) 24 | // } 25 | do { 26 | let path = FSPath(URL(fileURLWithPath: "/tmp")) 27 | XCTAssertEqual(path.path, "/tmp") 28 | } 29 | do { 30 | let path = FSPath("~") 31 | XCTAssertEqual(path.normalized.path, ("~" as NSString).expandingTildeInPath) 32 | } 33 | do { 34 | let path = FSPath("/tmp") 35 | XCTAssertEqual(path.components.count, 2) 36 | XCTAssertEqual(path.components[0], "/") 37 | XCTAssertEqual(path.components[1], "tmp") 38 | XCTAssertEqual(path.parent!, FSPath("/")) 39 | } 40 | do { 41 | XCTAssertTrue(FSPath("/") < FSPath("/tmp")) 42 | } 43 | do { 44 | let path = FSPath("foo.bar.zip") 45 | XCTAssertEqual(path.pathExtensions.count, 2) 46 | XCTAssertEqual(path.pathExtensions[0], "bar") 47 | XCTAssertEqual(path.pathExtensions[1], "zip") 48 | } 49 | // do { 50 | // let path = Path("/tmp/foo.bar.zip") 51 | // XCTAssertEqual(path.stem, "foo") 52 | // } 53 | do { 54 | let path = FSPath("/tmp/foo.bar.zip").withName("xyzzy") 55 | XCTAssertEqual(path.path, "/tmp/xyzzy") 56 | } 57 | // do { 58 | // let path = Path("/tmp/foo.bar.zip").withPathExtension(".bz2") 59 | // XCTAssertEqual(String(path), "/tmp/foo.bar.bz2") 60 | // } 61 | do { 62 | let path = FSPath("/tmp/foo.bar.zip").withStem("xyzzy") 63 | XCTAssertEqual(path.path, "/tmp/xyzzy.zip") 64 | } 65 | } 66 | 67 | // TODO: Failing test 68 | // func test1() { 69 | // try! FSPath.withTemporaryDirectory { 70 | // directory in 71 | // 72 | // let file = directory + "test.txt" 73 | // XCTAssertFalse(file.exists) 74 | // 75 | // XCTAssertEqual(file.name, "test.txt") 76 | // XCTAssertEqual(file.pathExtension, "txt") 77 | // 78 | // try file.createFile() 79 | // XCTAssertTrue(file.exists) 80 | // } 81 | // } 82 | } 83 | -------------------------------------------------------------------------------- /Tests/EverythingTests/ProcessTest.swift: -------------------------------------------------------------------------------- 1 | #if os(macOS) 2 | 3 | @testable import Everything 4 | import XCTest 5 | 6 | class ProcessTest: XCTestCase { 7 | func test1() throws { 8 | let result = try Process.checkOutputString(launchPath: "/bin/echo", arguments: ["-n", "Hello world"]) 9 | XCTAssertEqual(result, "Hello world") 10 | } 11 | 12 | func test2() throws { 13 | XCTAssertThrowsError(try Process.checkOutputString(launchPath: "/usr/bin/false", arguments: [])) 14 | } 15 | 16 | func test4() throws { 17 | let result = try Process.checkOutput(launchPath: "/usr/bin/true", arguments: []) 18 | XCTAssertEqual(result.terminationStatus, 0) 19 | } 20 | 21 | func test5() throws { 22 | let output = try FileHandle.temp(template: "XXXXXXXX.txt", suffixLength: 4) 23 | let result = try Process.call(launchPath: "/bin/echo", arguments: ["-n", "Hello world"], standardOutput: .fileHandle(output)) 24 | XCTAssertEqual(result.terminationStatus, 0) 25 | try output.seek(toOffset: 0) 26 | let s = try String(decoding: output.readToEnd()!, as: UTF8.self) 27 | XCTAssertEqual(s, "Hello world") 28 | } 29 | 30 | // func test6() throws { 31 | // let result = try Process.checkOutput(launchPath: "/usr/bin/python3", arguments: ["-c", "import sys; sys.stderr.write('Hello world')"]) 32 | // XCTAssertEqual(result.terminationStatus, 0) 33 | // XCTAssertEqual(try result.standardError!.read().toString(), "Hello world") 34 | // } 35 | 36 | // func test7() throws { 37 | // let result = try Process.checkOutput(launchPath: "/usr/bin/python3", arguments: ["-c", "import sys; sys.stderr.write('Hello'); sys.stderr.write(' world')"], options: .combinedOutput) 38 | // XCTAssertEqual(result.terminationStatus, 0) 39 | // XCTAssertEqual(try result.standardError!.read().toString(), "Hello world") 40 | // } 41 | } 42 | 43 | extension Data { 44 | func toString() -> String { 45 | String(decoding: self, as: UTF8.self) 46 | } 47 | } 48 | 49 | extension FileHandle { 50 | static func temp(template: String, suffixLength: Int) throws -> FileHandle { 51 | var template = template.utf8CString 52 | return template.withUnsafeMutableBufferPointer { buffer in 53 | let result = mkstemps(buffer.baseAddress, Int32(suffixLength)) 54 | guard result > 0 else { 55 | fatalError("mkstemp failed") 56 | } 57 | return FileHandle(fileDescriptor: result, closeOnDealloc: true) 58 | } 59 | } 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /Tests/EverythingTests/RandomTests.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import Foundation 3 | import XCTest 4 | 5 | class RandomTests: XCTestCase { 6 | func test1() { 7 | let weights: [Float] = [10] 8 | XCTAssertEqual(weights.weightedRandomIndex(), weights.startIndex) 9 | } 10 | 11 | func test2() { 12 | let weights: [Double] = [10] 13 | XCTAssertEqual(weights.weightedRandomIndex(), weights.startIndex) 14 | } 15 | 16 | func test3() { 17 | let weights: [Double] = [10, 0] 18 | XCTAssertEqual(weights.weightedRandomIndex(), weights.startIndex) 19 | } 20 | 21 | func test4() { 22 | let weights: [Double] = [10, 0, 0] 23 | XCTAssertEqual(weights.weightedRandomIndex(), weights.startIndex) 24 | } 25 | 26 | func test5() { 27 | let weights: [Double] = [10, 0, 0] 28 | let index = weights.weightedRandomIndex() 29 | XCTAssertEqual(weights[index], 10) 30 | } 31 | 32 | func test6() { 33 | let weights: [Double] = [0, 10, 0] 34 | let index = weights.weightedRandomIndex() 35 | XCTAssertEqual(weights[index], 10) 36 | } 37 | 38 | func test7() { 39 | let weights: [Double] = [0, 0, 10] 40 | let index = weights.weightedRandomIndex() 41 | XCTAssertEqual(weights[index], 10) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/EverythingTests/SIMDTests.swift: -------------------------------------------------------------------------------- 1 | //// 2 | //// File.swift 3 | //// 4 | //// 5 | //// Created by Jonathan Wight on 12/9/19. 6 | //// 7 | // 8 | // @testable import Everything 9 | // import Foundation 10 | // import simd 11 | // import XCTest 12 | // 13 | // class SIMDTests: XCTestCase { 14 | // func testVectors() { 15 | // XCTAssertEqual(SIMD2.zero, [0, 0]) 16 | // XCTAssertEqual(SIMD2.unit, [1, 1]) 17 | // XCTAssertEqual(SIMD2(1, 0).length, 1) 18 | // XCTAssertEqual(SIMD2(1, 1).length, 1.4142135, accuracy: 0.00001) 19 | // XCTAssertEqual(SIMD2(1, 2).map({ $0 * 2 }), [2, 4]) 20 | // XCTAssertEqual(SIMD3(1, 2, 3).map({ $0 * 2 }), [2, 4, 6]) 21 | // XCTAssertEqual(SIMD4(1, 2, 3, 4).map({ $0 * 2 }), [2, 4, 6, 8]) 22 | // XCTAssertEqual(SIMD3(1, 2, 3).xy, [1, 2]) 23 | // XCTAssertEqual(SIMD4(1, 2, 3, 4).xy, [1, 2]) 24 | // XCTAssertEqual(SIMD4(1, 2, 3, 4).xyz, [1, 2, 3]) 25 | // } 26 | // 27 | // func testMatrix1() { 28 | // XCTAssertEqual(simd_float3x3(truncating: simd_float4x4(diagonal: [1, 2, 3, 4])), simd_float3x3(diagonal: [1, 2, 3])) 29 | // } 30 | // 31 | // func testMatrix2() { 32 | // let m = simd_float4x4(diagonal: [1, 2, 3, 4]) 33 | // let s = m.prettyDescription.removingOccurances(of: .whitespaces) 34 | // XCTAssertEqual(s, "1.0,0.0,0.0,0.0\n0.0,2.0,0.0,0.0\n0.0,0.0,3.0,0.0\n0.0,0.0,0.0,4.0") 35 | // } 36 | // 37 | // func testMatrix3() { 38 | // let m = simd_float4x4(columns: ([1, 2, 3, 4], .zero, .zero, .zero)) 39 | // let s = m.prettyDescription.removingOccurances(of: .whitespaces) 40 | // XCTAssertEqual(s, "1.0,0.0,0.0,0.0\n2.0,0.0,0.0,0.0\n3.0,0.0,0.0,0.0\n4.0,0.0,0.0,0.0") 41 | // } 42 | // 43 | // func testMatrixRows() { 44 | // let m = simd_float4x4(rows: ([1, 2, 3, 4], .zero, .zero, .zero)) 45 | // let s = m.prettyDescription.removingOccurances(of: .whitespaces) 46 | // XCTAssertEqual(s, "1.0,2.0,3.0,4.0\n0.0,0.0,0.0,0.0\n0.0,0.0,0.0,0.0\n0.0,0.0,0.0,0.0") 47 | // } 48 | // 49 | // func testQuat() { 50 | // XCTAssertEqual(simd_quatf.identity, simd_quatf(angle: 0, axis: [0, 0, 0])) 51 | // XCTAssertEqual(simd_quatf.identity, simd_quatf(angle: 0, axis: [1, 0, 0])) 52 | // XCTAssertEqual(simd_quatf.identity, simd_quatf(angle: 0, axis: [0, 1, 0])) 53 | // XCTAssertEqual(simd_quatf.identity, simd_quatf(angle: 0, axis: [0, 0, 1])) 54 | // } 55 | // } 56 | // 57 | // public extension String { 58 | // init(_ input: F.FormatInput, format: F) where F : FormatStyle, F.FormatInput : Equatable, F.FormatOutput == String { 59 | // self = format.format(input) 60 | // } 61 | // } 62 | // 63 | // 64 | // 65 | // class TempTest: XCTestCase { 66 | // 67 | // func testX() { 68 | // print(simd_float4x4(translate: [10, 20, 30]).foo) 69 | // } 70 | // 71 | // func testAPI() { 72 | // let scalars = Array(stride(from: Float(0), through: 15, by: 1)) 73 | // XCTAssertEqual(simd_float4x4(scalars: scalars).scalars, scalars) 74 | // } 75 | // 76 | // } 77 | // 78 | // extension simd_float4x4 { 79 | // 80 | // init(scalars: [Float]) { 81 | // assert(scalars.count == 16) 82 | // self.init(columns: ( 83 | // SIMD4(scalars[0..<4]), 84 | // SIMD4(scalars[4..<8]), 85 | // SIMD4(scalars[8..<12]), 86 | // SIMD4(scalars[12...]) 87 | // )) 88 | // } 89 | // 90 | // var scalars: [Float] { 91 | // (0..<4).reduce(into: []) { result, column in 92 | // result += (0..<4).reduce(into: []) { result, row in 93 | // result.append(self[column][row]) 94 | // } 95 | // } 96 | // } 97 | // 98 | // 99 | // var foo: String { 100 | // let format = FloatingPointFormatStyle() 101 | // .precision(.significantDigits(8)) 102 | // let s = rows.map { row in 103 | // row.map { format.format($0) } 104 | // .joined(separator: ", ") 105 | // } 106 | // .joined(separator: "\n") 107 | // return s 108 | // } 109 | // } 110 | -------------------------------------------------------------------------------- /Tests/EverythingTests/TaggedTests.swift: -------------------------------------------------------------------------------- 1 | import Everything 2 | import XCTest 3 | 4 | class TaggedTests: XCTestCase { 5 | func test1() { 6 | enum FooTag {} 7 | typealias FooIdentifier = Tagged 8 | let id = FooIdentifier("x") 9 | let id2: FooIdentifier = "x" 10 | XCTAssertEqual(id, id2) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Tests/EverythingTests/Utilities.swift: -------------------------------------------------------------------------------- 1 | @testable import Everything 2 | import XCTest 3 | 4 | // func XCTAssertEqual(@autoclosure expression1: () -> T, @autoclosure _ expression2: () -> T, @autoclosure _ expression3: () -> T, message: String = "", file: String = __FILE__, line: UInt = __LINE__) { 5 | // XCTAssertEqual(expression1, expression2, message, file: file, line: line) 6 | // XCTAssertEqual(expression2, expression3, message, file: file, line: line) 7 | // XCTAssertEqual(expression3, expression1, message, file: file, line: line) 8 | // } 9 | 10 | // func XCTAssertThrows(_ closure: () throws -> Void) { 11 | // do { 12 | // try closure() 13 | // XCTAssert(false) 14 | // } 15 | // catch { 16 | // return 17 | // } 18 | // } 19 | 20 | func bits(_ bits: Int) -> Int { 21 | bits * 8 22 | } 23 | 24 | func buildBinary(_ count: Int, closure: (UnsafeMutableBufferPointer) -> Void) -> [UInt8] { 25 | var data = [UInt8](repeating: 0, count: Int(ceil(Double(count) / 8))) 26 | data.withUnsafeMutableBufferPointer { 27 | (buffer: inout UnsafeMutableBufferPointer) in 28 | closure(buffer) 29 | } 30 | return data 31 | } 32 | 33 | struct BitString { 34 | var string: String 35 | 36 | init(count: Int) { 37 | string = String(repeating: "0", count: count) 38 | } 39 | 40 | // mutating func bitSet(_ start: Int, length: Int, newValue: UIntMax) throws { 41 | // 42 | // let newValue = try binary(newValue, width: length, prefix: false) 43 | // 44 | // let start = string.index(string.startIndex, offsetBy: start) 45 | // let end = <#T##String.CharacterView corresponding to `start`##String.CharacterView#>.index(start, offsetBy: length) 46 | // string.replaceRange(start.. [XCTestCaseEntry] { 5 | [ 6 | testCase(EverythingTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/CharacterSetTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import SwiftParsing 4 | 5 | class CharacterSetTests: XCTestCase { 6 | func testExample() { 7 | let set = SimpleCharacterSet.whitespaces 8 | 9 | XCTAssertTrue(set.contains(" ")) 10 | XCTAssertTrue(set.contains("\n")) 11 | XCTAssertTrue(set.contains("\r")) 12 | XCTAssertTrue(set.contains("\t")) 13 | 14 | XCTAssertFalse(set.contains("x")) 15 | XCTAssertFalse(set.contains("\\")) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/JSONPathParsingTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import SwiftParsing 4 | 5 | // class JSONPathParsingTests: XCTestCase { 6 | // var json: AnyObject! 7 | // 8 | // override func setUp() { 9 | // let bundle = Bundle(for: type(of: self)) 10 | // let url = bundle.url(forResource: "sample", withExtension: "json")! 11 | // let data = try! Data(contentsOf: url) 12 | // json = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as AnyObject! 13 | // } 14 | // 15 | // // MARK: test 1 16 | // // the authors of all books in the store 17 | // func test1() { 18 | // let path = try! JSONPath("$.store.book[*].author", compile: true) 19 | // let result: [String] = try! path.evaluate(json!) 20 | // let expected = ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"] 21 | // zip(result, expected).forEach() { 22 | // XCTAssertEqual($0, $1) 23 | // } 24 | // } 25 | // 26 | // // MARK: test 1 alt 1 27 | // // the authors of all books in the store 28 | // func test1_alt1() { 29 | // let path = try! JSONPath("$[store][book][*][author]", compile: true) 30 | // let result: [String] = try! path.evaluate(json!) 31 | // let expected = ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"] 32 | // zip(result, expected).forEach() { 33 | // XCTAssertEqual($0, $1) 34 | // } 35 | // } 36 | // 37 | // // MARK: test 1 alt 2 38 | // // the authors of all books in the store 39 | // func test1_alt2() { 40 | // let path = try! JSONPath("$.store.book.*.author", compile: true) 41 | // let result: [String] = try! path.evaluate(json!) 42 | // let expected = ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"] 43 | // zip(result, expected).forEach() { 44 | // XCTAssertEqual($0, $1) 45 | // } 46 | // } 47 | // 48 | // // MARK: test2 49 | // // $..author 50 | // 51 | // // MARK: test3 52 | // // ? 53 | // 54 | // // MARK: test4 55 | // // $.store..price 56 | // 57 | // // MARK: test5 58 | // // $..book[2] 59 | // 60 | // // MARK: test6 61 | // //$..book[(@.length-1)] 62 | // //$..book[-1: ] 63 | // 64 | // // MARK: Test 7 65 | // //$..book[0,1] 66 | // //$..book[:2] 67 | // 68 | // // MARK: Test 8 69 | // //$..book[?(@.isbn)] 70 | // 71 | // // MARK: Test 9 72 | // //$..book[?(@.price<10)] 73 | // 74 | // 75 | // // MARK: Test 10 76 | // //$..* 77 | // 78 | // 79 | // // MARK: Custom Tests 80 | // 81 | // 82 | // func test_custom_1() { 83 | // let path = try! JSONPath("$.store.book.0.title", compile: true) 84 | // let result = try! path.evaluate(json!) 85 | // XCTAssertEqual(result as? String, "Sayings of the Century") 86 | // } 87 | // 88 | // func test_custom_2() { 89 | // let path = try! JSONPath("$.store.book.0.price", compile: true) 90 | // let result = try! path.evaluate(json!) 91 | // XCTAssertEqual(result as? Double, 8.95) 92 | // } 93 | // 94 | // func test_custom_3() { 95 | // let path = try! JSONPath("$.store.book.0[title,author]", compile: true) 96 | // let result = try! path.evaluate(json!) as! [AnyObject] 97 | // XCTAssertEqual(result[0] as? String, "Sayings of the Century") 98 | // XCTAssertEqual(result[1] as? String, "Nigel Rees") 99 | // } 100 | // 101 | // } 102 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/ParserTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import SwiftParsing 4 | 5 | class ParserTests: XCTestCase { 6 | func testDelimitedList() { 7 | let identifier = identifierValue() 8 | let list = DelimitedList(subelement: identifier, min: 2, max: 2) 9 | let result = try! list.parse("hello, world") as! [Any] 10 | XCTAssertEqual(result[0] as? String, "hello") 11 | XCTAssertEqual(result[1] as? String, "world") 12 | } 13 | 14 | func testExample() { 15 | let wildcardSelector = Literal("*") 16 | let nameSelector = try! Pattern("^[a-zA-Z_]+") 17 | let indexedSelector = try! Pattern("^[0-9]+") 18 | 19 | let LBRACKET = Literal("[").makeStripped() 20 | let RBRACKET = Literal("]").makeStripped() 21 | let COMMA = Literal(",").makeStripped() 22 | 23 | let rootOperator = Literal("$").makeStripped() 24 | let dotOperator = Literal(".") 25 | 26 | let selector = (nameSelector | indexedSelector | wildcardSelector) 27 | 28 | let dotPathElement = (dotOperator + selector) 29 | 30 | let nameSelectorsList = (nameSelector + zeroOrMore(COMMA + nameSelector).setID("#1")) 31 | let bracketPathElement = (LBRACKET + (nameSelectorsList | selector) + RBRACKET) 32 | 33 | let pathElement = (dotPathElement | bracketPathElement) 34 | 35 | let path = (rootOperator + oneOrMore(pathElement).setID("#2")) 36 | 37 | let parser = (path + atEnd) 38 | 39 | let result = try! parser.parse("$[foo,bar]") 40 | print(result as Any) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/ScannerTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import SwiftParsing 4 | 5 | func XCTAssertNoThrow(_ block: () throws -> Void) { 6 | do { 7 | try block() 8 | } 9 | catch { 10 | XCTAssertTrue(false) 11 | } 12 | } 13 | 14 | func XCTAssertThrows(_ block: () throws -> Void) { 15 | do { 16 | try block() 17 | } 18 | catch { 19 | return 20 | } 21 | XCTAssertTrue(false) 22 | } 23 | 24 | class ScannerTests: XCTestCase { 25 | func testScanSimpleString() { 26 | let scanner = SwiftParsing.Scanner(string: "Hello world") 27 | XCTAssert(scanner.scan(string: "Hello") == true) 28 | XCTAssert(scanner.scan(string: "world") == true) 29 | XCTAssert(scanner.atEnd == true) 30 | } 31 | 32 | func testScanTooMuchSimpleString() { 33 | let scanner = SwiftParsing.Scanner(string: "Hello") 34 | XCTAssert(scanner.scan(string: "Hello world") == false) 35 | XCTAssert(scanner.atEnd == false) 36 | } 37 | 38 | func testScanCharSet() { 39 | let scanner = SwiftParsing.Scanner(string: "01234") 40 | XCTAssert(scanner.scan(charactersFromSet: SimpleCharacterSet.decimalDigits) == "01234") 41 | XCTAssert(scanner.atEnd == true) 42 | } 43 | 44 | func testBadScanCharSet() { 45 | let scanner = SwiftParsing.Scanner(string: "abcde") 46 | XCTAssert(scanner.scan(charactersFromSet: SimpleCharacterSet.decimalDigits) == nil) 47 | XCTAssert(scanner.atEnd == false) 48 | } 49 | 50 | func testScanSingleCharSet() { 51 | let scanner = SwiftParsing.Scanner(string: "0") 52 | XCTAssert(scanner.scan(characterFromSet: SimpleCharacterSet.decimalDigits) == Character("0")) 53 | XCTAssert(scanner.atEnd == true) 54 | } 55 | 56 | func testScanNoSingleCharSet() { 57 | let scanner = SwiftParsing.Scanner(string: "A") 58 | XCTAssert(scanner.scan(characterFromSet: SimpleCharacterSet.decimalDigits) == nil) 59 | XCTAssert(scanner.atEnd == false) 60 | } 61 | 62 | func testScanSingleChar() { 63 | let scanner = SwiftParsing.Scanner(string: "0A") 64 | XCTAssert(scanner.scan(character: Character("0")) == true) 65 | XCTAssert(scanner.scan(character: Character("X")) == false) 66 | } 67 | 68 | func testScanSimpleStringNoSkip() { 69 | let scanner = SwiftParsing.Scanner(string: "Hello world") 70 | scanner.skippedCharacters = nil 71 | XCTAssert(scanner.scan(string: "Hello") == true) 72 | XCTAssert(scanner.scan(string: " ") == true) 73 | XCTAssert(scanner.scan(string: "world") == true) 74 | XCTAssert(scanner.atEnd == true) 75 | } 76 | 77 | func testScanSuppressSkip() { 78 | let scanner = SwiftParsing.Scanner(string: "Hello world") 79 | scanner.suppressSkip() { 80 | XCTAssert(scanner.scan(string: "Hello") == true) 81 | XCTAssert(scanner.scan(string: " ") == true) 82 | XCTAssert(scanner.scan(string: "world") == true) 83 | XCTAssert(scanner.atEnd == true) 84 | } 85 | } 86 | 87 | func testScanBadBack() { 88 | let scanner = SwiftParsing.Scanner(string: "") 89 | XCTAssertThrows { 90 | try scanner.back() 91 | } 92 | } 93 | 94 | func testScanRegularExpression() { 95 | let scanner = SwiftParsing.Scanner(string: "Hello world") 96 | let result = try! scanner.scan(regularExpression: "H[^\\s]+") 97 | XCTAssert(result == "Hello") 98 | XCTAssert(scanner.remaining == " world") 99 | 100 | let result2 = try! scanner.scan(regularExpression: "w[^\\s]+") 101 | XCTAssert(result2 == "world") 102 | } 103 | 104 | func testScanNotRegularExpression() { 105 | let scanner = SwiftParsing.Scanner(string: "Hello world") 106 | let result = try! scanner.scan(regularExpression: "[0-9]+") 107 | XCTAssert(result == nil) 108 | } 109 | 110 | func testScanRegularExpression2() { 111 | let scanner = SwiftParsing.Scanner(string: "name") 112 | XCTAssertEqual(try! scanner.scan(regularExpression: "[A-Za-z_]+"), "name") 113 | } 114 | 115 | func testEmpty() { 116 | let scanner = SwiftParsing.Scanner(string: "") 117 | _ = scanner.scan(string: "X") 118 | } 119 | 120 | func testScanFiddlyJSONPath() { 121 | let scanner = SwiftParsing.Scanner(string: "$.store.book[0].title") 122 | 123 | XCTAssert(scanner.scan(string: "$") == true) 124 | XCTAssert(scanner.scan(string: ".") == true) 125 | XCTAssertEqual(try! scanner.scan(regularExpression: "[\\w_]+"), "store") 126 | XCTAssert(scanner.scan(string: ".") == true) 127 | XCTAssertEqual(try! scanner.scan(regularExpression: "[\\w_]+"), "book") 128 | XCTAssert(scanner.scan(string: "[") == true) 129 | XCTAssertEqual(try! scanner.scan(regularExpression: "[\\d_]+"), "0") 130 | XCTAssert(scanner.scan(string: "]") == true) 131 | XCTAssert(scanner.scan(string: ".") == true) 132 | XCTAssertEqual(try! scanner.scan(regularExpression: "[\\w_]+"), "title") 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/SwiftParsingTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | class SwiftParsingTests: XCTestCase { 4 | override func setUp() { 5 | super.setUp() 6 | // Put setup code here. This method is called before the invocation of each test method in the class. 7 | } 8 | 9 | override func tearDown() { 10 | // Put teardown code here. This method is called after the invocation of each test method in the class. 11 | super.tearDown() 12 | } 13 | 14 | func testExample() { 15 | // This is an example of a functional test case. 16 | // Use XCTAssert and related functions to verify your tests produce the correct results. 17 | } 18 | 19 | func testPerformanceExample() { 20 | // This is an example of a performance test case. 21 | measure { 22 | // Put the code you want to measure the time of here. 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/SwiftTransformParsingTests.swift: -------------------------------------------------------------------------------- 1 | import SwiftParsing 2 | import XCTest 3 | 4 | let COMMA = Literal(",") 5 | let OPT_COMMA = zeroOrOne(COMMA).makeStripped() 6 | let LPAREN = Literal("(").makeStripped() 7 | let RPAREN = Literal(")").makeStripped() 8 | let VALUE_LIST = oneOrMore((DoubleValue() + OPT_COMMA).makeStripped().makeFlattened()) 9 | 10 | // TODO: Should set manual min and max value instead of relying on 0.. [XCTestCaseEntry] { 5 | [ 6 | testCase(SwiftParsingTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /Tests/SwiftParsingTests/sample.json: -------------------------------------------------------------------------------- 1 | { "store": { 2 | "book": [ 3 | { "category": "reference", 4 | "author": "Nigel Rees", 5 | "title": "Sayings of the Century", 6 | "price": 8.95 7 | }, 8 | { "category": "fiction", 9 | "author": "Evelyn Waugh", 10 | "title": "Sword of Honour", 11 | "price": 12.99 12 | }, 13 | { "category": "fiction", 14 | "author": "Herman Melville", 15 | "title": "Moby Dick", 16 | "isbn": "0-553-21311-3", 17 | "price": 8.99 18 | }, 19 | { "category": "fiction", 20 | "author": "J. R. R. Tolkien", 21 | "title": "The Lord of the Rings", 22 | "isbn": "0-395-19395-8", 23 | "price": 22.99 24 | } 25 | ], 26 | "bicycle": { 27 | "color": "red", 28 | "price": 19.95 29 | } 30 | } 31 | } --------------------------------------------------------------------------------