Skip to content

Instantly share code, notes, and snippets.

@jon-cotton
Last active December 18, 2015 14:23
Show Gist options
  • Save jon-cotton/796915ca88350d0ccf2c to your computer and use it in GitHub Desktop.
Save jon-cotton/796915ca88350d0ccf2c to your computer and use it in GitHub Desktop.
//
// SemanticVersionNumber.swift
//
// Created by Jon Cotton on 31/08/2015.
//
import Foundation
public struct SemanticVersionNumber {
let major: Int
let minor: Int
let patch: Int
public init(_ versionString: String) {
let components = versionString.componentsSeparatedByString(".")
var major = 0
var minor = 0
var patch = 0
switch components.count {
case 3...999:
patch = Int(components[2]) ?? 0
fallthrough
case 2...999:
minor = Int(components[1]) ?? 0
fallthrough
case 1...999:
major = Int(components[0]) ?? 0
default:
major = 0
minor = 0
patch = 0
}
self.major = major
self.minor = minor
self.patch = patch
}
}
extension SemanticVersionNumber : CustomStringConvertible {
public var description: String {return "\(major).\(minor).\(patch)"}
}
extension SemanticVersionNumber : Equatable {}
public func == (lhs: SemanticVersionNumber, rhs: SemanticVersionNumber) -> Bool {
return (lhs.major == rhs.major &&
lhs.minor == rhs.minor &&
lhs.patch == rhs.patch)
}
extension SemanticVersionNumber : Comparable {}
public func < (lhs: SemanticVersionNumber, rhs: SemanticVersionNumber) -> Bool {
var returnVal = false
if lhs.major < rhs.major {
returnVal = true
} else if lhs.major == rhs.major {
if lhs.minor < rhs.minor {
returnVal = true
} else if lhs.minor == rhs.minor {
if lhs.patch < rhs.patch {
returnVal = true
}
}
}
return returnVal
}
extension SemanticVersionNumber : StringLiteralConvertible {
public typealias UnicodeScalarLiteralType = StringLiteralType
public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
public init(stringLiteral value: StringLiteralType) {
self.init(value)
}
}
////////////////////////////////////////////////
// TESTS
////////////////////////////////////////////////
//
// SemanticVersionNumberTests.swift
//
// Created by Jon Cotton on 31/08/2015.
//
import Foundation
import XCTest
class SemanticVersionNumberTests: XCTestCase {
func testVersionNumberIsCreatedCorrectlyWithCleanInput() {
let version: SemanticVersionNumber = "1.2.3"
XCTAssert(version.major == 1, "Major component of version number is an unexpected value when init'd with a clean string")
XCTAssert(version.minor == 2, "Minor component of version number is an unexpected value when init'd with a clean string")
XCTAssert(version.patch == 3, "Patch component of version number is an unexpected value when init'd with a clean string")
}
func testVersionNumberIsCreatedCorrectlyWithDirtyInput() {
let version: SemanticVersionNumber = "1a.2.3b"
XCTAssert(version.major == 0, "Major component of version number is an unexpected value when init'd with a dirty string")
XCTAssert(version.minor == 2, "Minor component of version number is an unexpected value when init'd with a dirty string")
XCTAssert(version.patch == 0, "Patch component of version number is an unexpected value when init'd with a dirty string")
}
func testVersionNumberEquatable() {
let version1: SemanticVersionNumber = "1"
let version2: SemanticVersionNumber = "1.0.0"
XCTAssert(version1 == version2, "Expected both versions to be equal")
}
func testVersionNumberComparable() {
let version1: SemanticVersionNumber = "1"
let version2: SemanticVersionNumber = "1.0.1"
XCTAssert(version1 < version2, "Expected version 1 to be less than version 2")
}
}
@jon-cotton
Copy link
Author

let versionNumber1: SemanticVersionNumber = "1.1.2"
let versionNumber2: SemanticVersionNumber = "2.0.2"

(versionNumber2 > versionNumber1) // returns true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment