Swiftpack.co - Package - SDGGiesbrecht/SDGCornerstone


macOS • Linux • iOS • watchOS • tvOS

APIs: SDGCornerstoneSDGCornerstoneTestUtilitiesSDGXCTestUtilitiesSDGControlFlowSDGLogicSDGLogicTestUtilitiesSDGMathematicsSDGMathematicsTestUtilitiesSDGCollectionsSDGCollectionsTestUtilitiesSDGBinaryDataSDGTextSDGPersistenceSDGPersistenceTestUtilitiesSDGRandomizationSDGRandomizationTestUtilitiesSDGLocalizationSDGLocalizationTestUtilitiesSDGGeometrySDGCalendarSDGPrecisionMathematicsSDGConcurrencySDGExternalProcessSDGTesting


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.



  • 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.
  • Customizable randomization.
  • 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.)


SDGCornerstone is intended for use with the Swift Package Manager.

Simply add SDGCornerstone as a dependency in Package.swift:

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/SDGGiesbrecht/SDGCornerstone", .upToNextMinor(from: Version(0, 9, 4))),
    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: "SDGCalendar", package: "SDGCornerstone"),
            .productItem(name: "SDGPrecisionMathematics", package: "SDGCornerstone"),
            .productItem(name: "SDGConcurrency", package: "SDGCornerstone"),
            .productItem(name: "SDGExternalProcess", package: "SDGCornerstone"),
            .productItem(name: "SDGTesting", package: "SDGCornerstone"),

SDGCornerstone 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 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
               "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)

               "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)

} catch {

// ••••••• 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"

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

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let pattern = CompositePattern([
    LiteralPattern([1]), // 1
    ConditionalPattern({ $0.isEven }), // 2
        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)

// ••••••• Randomization •••••••

func rollDie() -> Int {
    return Int(randomInRange: 1 ... 6)

if rollDie() == 1 ∧ rollDie() == 1 {
    print("Snake eyes!")
} else {
    print("Not this time...")

// ••••••• 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!"]),
               "Hello, world!")


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.



Stars: 7
Help us keep the lights on



0.9.4 - May 18, 2018

Bug Fixes

  • FileConvertible falls back to NFD and NFC versions of the URL if the initial load attempt fails.
  • ExternalProcess inherits the quality of service of the thread from which it is run.
  • TestCase runs tests under the “utility” quality of service.

0.9.3 - May 2, 2018

New Features

  • FileManager can now simplify deep file enumeration: deepFileEnumeration(in:)
  • Ranges are now Hashable wherever their Bound type is Hashable.

0.9.2 - Apr 30, 2018

Bug Fixes

  • TestCase is now compatible with Swift’s --generate-linuxmain.

0.9.1 - Apr 26, 2018

New Features

  • Search‐based initializer for ExternalProcess.

0.9.0 - Apr 22, 2018

Breaking Changes

  • Fixed spelling of the SDGCornerstoneTestUtilities product.
  • UserFacingText<L> has been made generic. UserFacing<StrictString, L> is equivalent to the old, but other elements can now be used in place of StrictString, such as images or mark‐up .
  • Collection search operations have been extracted to their own protocols, SearchableCollection and BidirectionalSearchableCollection.
    • Ordered collections conform to these wherever their elements are Equatable: Array, Data, String, etc.
    • Unordered collections do not conform and no longer have misleading access to search methods: Set, Dictionary, BijectiveMapping, etc.
  • Operators may require additional import statements to use. (A compiler bug prevents modules from exporting operators from another module. Originally, SDGCornerstone modules redeclared them as a workaround. Unfortunately this led to definition conflicts. With the exception of the SDGCornerstone module—which is not expected to be imported alongside its particular components—, the duplicate declarations have been removed. Until the compiler bug is fixed, the module where the operator is originally declared must now be imported as well.)
  • LineIndex has been renamed to LineViewIndex.
  • RealArithmetic has additional conformance requirements.
  • Minor API nuances have changed due to the application of new Swift 4.1 features:
    • Conditional conformances replace operator overloads (such as ≠ with arrays).
    • Some new protocol constraints were added which the compiler could not previously handle.

New Features

  • Resolution of SemanticMarkup to other formats:
    • Rich text as NSAttributedString: richText(font:)
    • HTML: html()
  • N‐ary mathematical operations for use with any Sequence type.
  • Better support for logging, reflection and playground display.

Bug Fixes

  • SDGXCTestUtilities is now properly vended as a product.