Swiftpack.co - Package - SDGGiesbrecht/SDGCornerstone

macOS • Windows • Web • CentOS • Ubuntu • tvOS • iOS • Android • Amazon Linux • watchOS



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. (SDGLocalization)
  • User preferences compatible with Linux. (PreferenceSet, Preference)
  • Platform‐independent access to best‐practice file system locations. (url(for:in:at:))
  • Shared instances of value types. (Shared<Value>)
  • Generic pattern matching. (SearchableCollection, Pattern<Element>)
  • Customizable randomization. (SDGRandomization)
  • Arbitrary‐precision arithmetic. (SDGPrecisionMathematics)
  • A simple API for running shell commands on desktop platforms. (SDGExternalProcess)

...and much more.

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 {
  @SharedProperty var property: String = ""

let originalOwner = Owner()
originalOwner.property = "original"
let anotherOwner = Owner()
anotherOwner.$property = originalOwner.$property

anotherOwner.property = "changed"

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

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let patternFirstPart =
  [1]  // 1
  + ConditionalPattern({ $0.isEven })  // 2
  + ([30, 40]  // (∅)
    ∨ [3, 4])  // 3, 4
let pattern =
  + RepetitionPattern(¬[5, 7])  // 5, 6, 7, 8, 9 (...)
  + [10]  // 10

  numbers.firstMatch(for: pattern)?.range,

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

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

#if !(os(tvOS) || os(iOS) || os(watchOS))
    try? Shell.default.run(command: ["echo", "Hello, world!"]).get(),
    "Hello, world!"


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: [
      name: "SDGCornerstone",
      url: "https://github.com/SDGGiesbrecht/SDGCornerstone",
      from: Version(6, 2, 0)
  targets: [
      name: "MyTarget",
      dependencies: [
        .product(name: "SDGControlFlow", package: "SDGCornerstone"),
        .product(name: "SDGLogic", package: "SDGCornerstone"),
        .product(name: "SDGLogicTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGMathematics", package: "SDGCornerstone"),
        .product(name: "SDGMathematicsTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGCollections", package: "SDGCornerstone"),
        .product(name: "SDGCollectionsTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGBinaryData", package: "SDGCornerstone"),
        .product(name: "SDGText", package: "SDGCornerstone"),
        .product(name: "SDGCollation", package: "SDGCornerstone"),
        .product(name: "SDGPersistence", package: "SDGCornerstone"),
        .product(name: "SDGPersistenceTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGRandomization", package: "SDGCornerstone"),
        .product(name: "SDGRandomizationTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGLocalization", package: "SDGCornerstone"),
        .product(name: "SDGLocalizationTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGGeometry", package: "SDGCornerstone"),
        .product(name: "SDGGeometryTestUtilities", package: "SDGCornerstone"),
        .product(name: "SDGCalendar", package: "SDGCornerstone"),
        .product(name: "SDGPrecisionMathematics", package: "SDGCornerstone"),
        .product(name: "SDGConcurrency", package: "SDGCornerstone"),
        .product(name: "SDGExternalProcess", package: "SDGCornerstone"),
        .product(name: "SDGVersioning", package: "SDGCornerstone"),
        .product(name: "SDGTesting", package: "SDGCornerstone"),
        .product(name: "SDGXCTestUtilities", package: "SDGCornerstone"),

The modules can then be imported in source files:

import SDGControlFlow
import SDGLogic
import SDGLogicTestUtilities
import SDGMathematics
import SDGMathematicsTestUtilities
import SDGCollections
import SDGCollectionsTestUtilities
import SDGBinaryData
import SDGText
import SDGCollation
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 SDGVersioning
import SDGTesting
import SDGXCTestUtilities


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: 18


Used By

Total: 0


Version 6.2.0 -

New Features

  • Less of the API is disabled on the web platform (because parts of Foundation are now available).

Version 6.1.1 -

Bug Fixes

  • FileConvertible does not hang when attempting to load a remote file.

Version 6.1.0 -

New Features

  • Float16 is now supported.
  • Types such as ExternalProcess and Shell are now available even on platforms which prohibit their execution. This provides universal access to their namespaces and allows them to be used abstractly in data models.

Bug Fixes

  • The API has been updated to use #fileID and #filePath.
  • Windows now detects the system language setting.
  • deepFileEnumeration(in:) works on Windows even if the URL was not initialized as a directory URL.
  • OrderedEnumeration no longer overrides the synthesized Comparable implementation.

Version 6.0.0 -

Breaking Changes

  • Swift 5.3
  • StringFamily’s joined(separator:) has had its constraints narrowed on all platforms (to be just like it already was on web). This evades a bug in the 5.3 compiler that would otherwise prevent compilation.

Version 5.5.0 -

New Features

  • CentOS and Amazon Linux are now supported.

Bug Fixes

  • When searching for executables, PATH entries will be tried directly if which is not present.

Version 5.4.1 -

Bug Fixes

  • Windows stability has been improved.

Version 5.4.0 -

New Features

  • OrderedSet
  • Named types for wrapping tuples to attach protocol conformances: Tuple2, Tuple3, etc.

Version 5.3.2 -

Dependency updates.

Version 5.3.1 -

Bug Fixes

  • ContextualMapping properly uses the fallback algorithm even in the middle of an incomplete match.

Version 5.3.0 -

New Features

  • compare now has variants with up to four sort criteria.
  • LexicographicalComparison can be used to conveniently wrap any ordered collection and make it comparable without adding a retroactive conformance, such as to use Array with APIs that require Comparable conformance.

Version 5.2.0 -

New Features

  • Localization utilities support more inflection patterns.
  • The existing Unicode representation of a path in the file system can be looked up with existingRepresentation(of:).

Bug Fixes

  • File system operations automatically handle canonical Unicode equivalence in paths even where the file system itself has neglected to do so.

Version 5.1.0 -

New Features

  • On platforms with Combine, Shared<Value> conforms to ObservableObject.
  • Several types have improved print and playground representations.

Version 5.0.0 -

Breaking Changes

  • The Font type has been update to account for SwiftUI.
  • The autoreleasepool shim has been removed. purgingAutoreleased is an inlinable cross‐platform replacement.

Bug Fixes

  • Processes are found properly on Windows even when where reports multiple paths.

Version 4.6.2 -

Bug Fixes

  • Specifications detect differences in newlines. (Although on Windows, CR + LF is still treated as LF, so that if Git swaps line endings upon checkout, it won’t cause a failure.)
  • joined(separator:) for StringFamily is generic on Android like other platforms. (Web still cannot compile the generic form.)

Version 4.6.1 -

Breaking Changes

  • Swift 5.2 (Older Swift toolchains will not resolve this version.)

Version 4.6.0 -

New Features

  • Web is now supported. Actual runtime stability depends on the toolchain used to compile the package.

Version 4.5.0 -

New Features

  • StringFamily’s joined(separator:) is available for any Collection, not just Array.

Version 4.4.1 -

Bug Fixes

  • Several generic methods that had been removed on Android due to compiler bugs have been partially filled in with common specializations.

Version 4.4.0 -

New Features

  • SDGPersistenceTestUtilities’ specification directory respects SWIFTPM_PACKAGE_ROOT, so it can still be used even if the tests must be run from a different location than they were built. This allows it to work out‐of‐the‐box with Workspace’s continuous‐integration for Android.

Bug Fixes

  • On Android, using the temporary directory no longer leads to a crash.

Version 4.3.2 -

Dependency updates.

Version 4.3.1 -

Bug Fixes

  • Minor internal optimizations.

Version 4.3.0 -

New Features

  • Windows and Android are supported. Actual runtime stability depends on the toolchain used to compile the package. Some methods are disabled on Android to work around compiler bugs.

Version 4.2.1 -

Dependency updates.

Version 4.2.0 -

New Features

  • AnyLocalization is available to type‐erase localizations.

Bug Fixes

  • Data is available about more localizations.
  • The root collation has been improved.

Version 4.1.0 -

New Features

  • CoreGraphics types included in the core library edition of Foundation, such as CGFloat, now receive their extensions even when CoreGraphics itself is unavailable.

Bug Fixes

  • Where relevant, implementations have been deferred to the Swift project’s Numerics package.

Version 4.0.2 -

Bug Fixes

  • An overload has been added to disambiguate contains(_:) between Pattern and StringProtocol.

Version 4.0.1 -

Bug Fixes

  • Fix a bug where the comparison aids would report faulty orders in some situations.

Version 4.0.0 -

Breaking Changes

  • The Standard Library difference API has been adopted and legacy API removed. Shimming has been done so that it works on older platforms. Most of the shimmed API is identical, but several extension methods—which could not otherwise be disambiguated—have differing names:
    • changes(from:) instead of difference(from:)
    • applying(changes:) instead of applying(_:)

New Features

  • New short‐circuiting compare functions are available to simplify conforming to Comparable when multiple criteria are involved.

Version 3.1.0 -

New Features

  • Font has a new resized(to:) method. (Sunk from SDGInterface’s SDGTextDisplay.)

Bug Fixes

  • SemanticMarkup.richText(font:) now preserves the system font on macOS 10.15, even after the font has been resized.

Version 3.0.0 -

Breaking Changes

  • The pattern API has been rearranged to improve performance. The compiler can now do a much better job of specialization.
    • The Pattern base class has been removed and its subclasses converted to structures.
      • In its place, PatternProtocol has been shortened to simply Pattern.
    • LiteralPattern is no longer needed. Any SearchableCollection can be used directly.
    • Several pattern types have been renamed:
      • CompositePatternConcatenatedPatterns
      • NotPatternNegatedPattern
    • CompositePattern and AlternativePatterns have each been split into several layers that make different tradeoffs between performance and composability.
      1. ConcatenatedPatterns and AlternativePatterns represent heterogeneous pairs of patterns.
        • Pros:
          • These are fast, because the compiler can specialize them.
          • They can be composed at compile time to any level of complexity by stringing them together with + and .
        • Cons:
          • Composed types are heavily generic and make unwieldy properties, parameters or return types.
          • Composition cannot be done iteratively, since each addition changes the type.
      2. NaryConcatenatedPatterns and NaryAlternativePatterns represent n‐ary homogeneous collections of patterns.
        • Pros:
          • These are fast, because the compiler can specialize them.
          • They can be composed iteratively by constructing an array to pass to the initializer.
        • Cons:
          • All components must be of the same type.
      3. AnyPattern can be used to convert various patterns to the same type for use withNaryConcatenatedPatterns and NaryAlternativePatterns.
        • Pros:
          • Infinite composability.
        • Cons:
          • Not nearly as fast.
  • difference(from:) has been renamed to groupedDifferences(from:) to distinguish it from the similar method now available in the Standard Library on some platforms.
  • String index conversions now reflect the fact that the various views’ indices are merely type aliases of one another. Due to the absence of type safety, return values can now be nil if any index can lack a corresponding value, even those indices the type label does not intend. scalar(in:) can be used to get an unoptional scalar index. It rounds down when called on sub‐scalar indices by accident.

New Features

  • A new module, SDGVersioning, provides utilities for working with semantic versions. (It was formerly a part of the SDGSwift package.)
  • Several types can now be used as property wrappers:
    • Shared (indirectly via @SharedProperty). The projected value is the Shared reference.
    • Weak projects itself.