Swiftpack.co - Package - SDGGiesbrecht/SDGCornerstone

🇨🇦EN

macOS • Linux • iOS • watchOS • tvOS

Documentation

SDGCornerstone

SDGCornerstone forms the foundation of the SDG module family. It establishes design patterns and provides general‐use extensions to the Swift Standard Library and Foundation.

הִנְנִי יִסַּד בְּצִיּוֹן אָבֶן אֶבֶן בֹּחַן פִּנַּת יִקְרַת מוּסָד מוּסָד׃
Behold, I establish in Zion a stone, a tested stone, a precious cornerstone, a sure foundation.

                                                                                                    ―⁧יהוה⁩/Yehova

Features

  • Localization tools (compatible with the Swift Package Manager and Linux).
  • User preferences access (compatible with Linux).
  • Platform‐independent access to best‐practice file system locations.
  • Shared instances of value types.
  • Generic pattern matching.
  • Arbitrary‐precision arithmetic.
  • Simple API for running shell commands (desktop platforms only).

...and much more.

Use the entire package together by importing the SDGCornerstone product, or pick and choose pieces by importing the various component products.

(For a list of related projects, see here.)

Importing

SDGCornerstone provides libraries for use with the Swift Package Manager.

Simply add SDGCornerstone as a dependency in Package.swift and specify which of the libraries to use:

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/SDGGiesbrecht/SDGCornerstone", .upToNextMinor(from: Version(0, 18, 0))),
    ],
    targets: [
        .target(name: "MyTarget", dependencies: [
            .productItem(name: "SDGCornerstone", package: "SDGCornerstone"),
            .productItem(name: "SDGCornerstoneTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGXCTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGControlFlow", package: "SDGCornerstone"),
            .productItem(name: "SDGLogic", package: "SDGCornerstone"),
            .productItem(name: "SDGLogicTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGMathematics", package: "SDGCornerstone"),
            .productItem(name: "SDGMathematicsTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGCollections", package: "SDGCornerstone"),
            .productItem(name: "SDGCollectionsTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGBinaryData", package: "SDGCornerstone"),
            .productItem(name: "SDGText", package: "SDGCornerstone"),
            .productItem(name: "SDGPersistence", package: "SDGCornerstone"),
            .productItem(name: "SDGPersistenceTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGRandomization", package: "SDGCornerstone"),
            .productItem(name: "SDGRandomizationTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGLocalization", package: "SDGCornerstone"),
            .productItem(name: "SDGLocalizationTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGGeometry", package: "SDGCornerstone"),
            .productItem(name: "SDGGeometryTestUtilities", package: "SDGCornerstone"),
            .productItem(name: "SDGCalendar", package: "SDGCornerstone"),
            .productItem(name: "SDGPrecisionMathematics", package: "SDGCornerstone"),
            .productItem(name: "SDGConcurrency", package: "SDGCornerstone"),
            .productItem(name: "SDGExternalProcess", package: "SDGCornerstone"),
            .productItem(name: "SDGTesting", package: "SDGCornerstone"),
        ])
    ]
)

The libraries’ modules can then be imported in source files:

import SDGCornerstone
import SDGCornerstoneTestUtilities
import SDGXCTestUtilities
import SDGControlFlow
import SDGLogic
import SDGLogicTestUtilities
import SDGMathematics
import SDGMathematicsTestUtilities
import SDGCollections
import SDGCollectionsTestUtilities
import SDGBinaryData
import SDGText
import SDGPersistence
import SDGPersistenceTestUtilities
import SDGRandomization
import SDGRandomizationTestUtilities
import SDGLocalization
import SDGLocalizationTestUtilities
import SDGGeometry
import SDGGeometryTestUtilities
import SDGCalendar
import SDGPrecisionMathematics
import SDGConcurrency
import SDGExternalProcess
import SDGTesting

Example Usage

// ••••••• Localization •••••••

enum ApplicationLocalization : String, Localization {
    case english = "en"
    case français = "fr"
    static let fallbackLocalization = ApplicationLocalization.english
}

// Define
let text = UserFacing<StrictString, ApplicationLocalization>({ localization in
    switch localization {
    case .english:
        return "Hello, world!"
    case .français:
        return "Bonjour, le monde !"
    }
})

// Use
XCTAssertEqual(text.resolved(),
               "Hello, world!")

// ••••••• Preferences •••••••

let preferences = PreferenceSet.applicationPreferences

// Save
preferences["name"].value.set(to: "John Doe")
// Load
let loaded: String? = preferences["name"].value.as(String.self)

XCTAssertEqual(loaded,
               "John Doe")

// ••••••• File System •••••••

let url = FileManager.default.url(in: .applicationSupport, at: "folder/file.txt")
do {
    // Save
    try "Contents".save(to: url)
    // Load
    let loaded = try String(from: url)

    XCTAssertEqual(loaded,
                   "Contents")
} catch {
    XCTFail(error.localizedDescription)
}

// ••••••• Shared Values •••••••

class Owner {
    var property: Shared<String>
    init(property: Shared<String>) {
        self.property = property
    }
}

let originalOwner = Owner(property: Shared("original"))
let anotherOwner = Owner(property: originalOwner.property)

anotherOwner.property.value = "changed"
XCTAssertEqual(originalOwner.property.value,
               "changed")

// ••••••• Pattern Matching •••••••

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let pattern = CompositePattern([
    LiteralPattern([1]), // 1
    ConditionalPattern({ $0.isEven }), // 2
    AlternativePatterns([
        LiteralPattern([30, 40]), // (∅)
        LiteralPattern([3, 4]) // 3, 4
        ]),
    RepetitionPattern(NotPattern(LiteralPattern([5, 7]))), // 5, 6, 7, 8, 9 (...)
    LiteralPattern([10]) // 10
    ])

XCTAssertEqual(numbers.firstMatch(for: pattern)?.range,
               numbers.startIndex ..< numbers.endIndex)

// ••••••• Arbitrary Precision Arithmetic •••••••

let tenDuotrigintillion: WholeNumber = "10 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000"
XCTAssert(tenDuotrigintillion.isDivisible(by: 10))

#if !(os(iOS) || os(watchOS) || os(tvOS))

// ••••••• Shell Commands •••••••

XCTAssertEqual(try? Shell.default.run(command: ["echo", "Hello, world!"]).get(),
               "Hello, world!")
#endif

About

The SDGCornerstone project is maintained by Jeremy David Giesbrecht.

If SDGCornerstone saves you money, consider giving some of it as a donation.

If SDGCornerstone saves you time, consider devoting some of it to contributing back to the project.

Ἄξιος γὰρ ὁ ἐργάτης τοῦ μισθοῦ αὐτοῦ ἐστι.
For the worker is worthy of his wages.

                                                                                                    ―‎ישוע/Yeshuʼa

Github

link
Stars: 10
Help us keep the lights on

Dependencies

Releases

0.18.0 - May 7, 2019

Breaking Changes

  • Methods which throw specific errors types now do so using Result for stronger typing.
    • Affected initializers have been converted into static generator functions, because initializers cannot return a Result.
    • Methods which simply pass on untyped errors from Swift or Foundation are unaffected by this change; they continue to simply throw.
  • Minor adjustments have been made to the vector and point protocol hierarchies. Some protocols have been renamed with “Protocol” at the end to make room for concrete types. (e.g. TwoDimensionalPointTwoDimensionalPointProtocol)

New Features

  • Generic, cross‐platform two‐dimensional point and vector types are available.

0.17.1 - Apr 27, 2019

New Features

  • StrictString.StringInterpolation and SemanticMarkup.StringInterpolation are available for use by other types.

0.17.0 - Apr 20, 2019

Breaking Changes

  • iOS 11
  • watchOS 4
  • tvOS 11
  • Operators are no longer duplicated in the umbrella SDGCornerstone module. Import SDGLogic, SDGMathematics and SDGCollections directly to get access to them (until Swift properly exports operators).
  • Interpolation of strict strings and semantic markup require values to be converted to explicit text representations. Existing interpolations which rely on implicit description will no longer compile.
    var strict: StrictString = ""
    
    // String‐like types can be interpolated directly:
    let string: String = "Hello, world!"
    let character: Unicode.Scalar = "?"
    strict = "\(string) ...\(character)"
    
    // Most other types must be explicitly converted to some predictable text representation:
    let number = Int.random(in: 0 ... 1000)
    strict = "“\(number.inRomanNumerals())” means the same as “\(number.inDigits())”."
    
    // The Swift compiler’s own description of any value can still be requested explicitly:
    let something: Any = getError()
    strict = "Error: \(arbitraryDescriptionOf: something)"
    

Bug Fixes

  • Conditional patterns can be successfully compared against the end of a collection.

0.16.0 - Apr 5, 2019

Breaking Changes

  • iOS 10
  • watchOS 3
  • tvOS 10
  • BuildConfiguration has been removed. Use the package manager’s new build settings instead.
  • AdditiveArithmetic has been renamed to GenericAdditiveArithmetic and now inherits from the Standard Library’s AdditiveArithmetic.
    • additiveIdentity has been removed in favour of AdditiveArithmetic’s zero.
  • Recommended file system locations are now delegated to Foundation on Linux. The URLs may be different than with previous releases.

New Features

  • StrictString and SemanticMarkup conform to the new ExpressibleByStringInterpolation protocol.

0.15.0 - Mar 29, 2019

Breaking Changes

  • Swift 5
  • macOS 10.13