{"id":18031755,"url":"https://github.com/dagronf/dsfversion","last_synced_at":"2025-10-11T10:01:49.053Z","repository":{"id":63907415,"uuid":"292142815","full_name":"dagronf/DSFVersion","owner":"dagronf","description":"Swift 'Numeric Status Version' class supporting major, minor, patch and build integer values and version parsing.","archived":false,"fork":false,"pushed_at":"2024-07-09T08:17:47.000Z","size":50,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-23T04:31:40.557Z","etag":null,"topics":["ios","macos","swift","tvos","version","versioning"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dagronf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-02T00:59:16.000Z","updated_at":"2024-12-12T13:42:02.000Z","dependencies_parsed_at":"2024-10-30T10:21:13.747Z","dependency_job_id":null,"html_url":"https://github.com/dagronf/DSFVersion","commit_stats":{"total_commits":8,"total_committers":1,"mean_commits":8.0,"dds":0.0,"last_synced_commit":"ecf3af8ea1b7fcba95ee94d4e5f9d354a09fc7b4"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFVersion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFVersion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFVersion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFVersion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dagronf","download_url":"https://codeload.github.com/dagronf/DSFVersion/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245791341,"owners_count":20672665,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","macos","swift","tvos","version","versioning"],"created_at":"2024-10-30T10:10:40.315Z","updated_at":"2025-10-11T10:01:48.868Z","avatar_url":"https://github.com/dagronf.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Version\n\nA NumericalVersioning class supporting major, (optional) minor, (optional) patch and (optional) build fields.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/tag/dagronf/Version\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-5.0-orange.svg\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-lightgrey\" /\u003e\n    \u003ca href=\"https://swift.org/package-manager\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat\" alt=\"Swift Package Manager\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n## Why?\n\nI had the need to parse version strings from JSON and XML encoded files that met the following requirements…\n\n* Optional minor/patch/build fields\n* Extract a version from a string representation eg. `\"5.6.*\"`\n* The ability to use wildcards to support simple version checks\n* Version range checking\n* Swift Codable support\n\nThis class uses the [Numeric status](https://en.wikipedia.org/wiki/Software_versioning) versioning \nscheme (`major.minor.patch.build`).\n\nNote that you do not need to provide all fields! This class will work quite happily with just the major/minor combo \nif that's all you need within your project.\n\n## TL;DR: Simple example\n\n```swift\nlet lowerBound = Version(10,4)\nlet upperBound = Version(10,5)\n\nassert(lowerBound \u003c upperBound)\n\n// Simple checks to see version ordering\nlet testValue = Version(10,4,5,1001)\nassert(testValue \u003e lowerBound)\nassert(upperBound \u003e testValue)\n\n// Read from somewhere, and try to convert to a version definition\nlet strVer = \"10.4.5\"\nlet myVersion = try Version(strVer)   // Throws if strVer isn't a compatible version string\n\nassert(myVersion.major.rawValue == 10)\nassert(myVersion.minor.rawValue == 4)\nassert(myVersion.patch.rawValue == 5)\n\n// Simple comparison to verify if 'myVersion' is greater than our lower bound\nassert(lowerBound \u003c myVersion)\n\n// See whether 'myVersion' was within our required version range\nlet range = lowerBound ..\u003c upperBound\nassert(range.contains(myVersion))  \n```\n\n## Integration\n\nUse Swift Package Manager to add `https://github.com/dagronf/DSFVersion` to your project.\n\n## Rules\n\n### A field that is not provided when constructed is assumed to be 0. \n\n```swift\nVersion(10,4) ⟺ Version(10,4,0) ⟺ Version(10,4,0,0)\nVersion(\"5.6.3\") ⟺ Version(5,6,3,0) ⟺ Version(5,6,3)\n```\n\n### A field that is assigned to `UInt.wildcard` is defined as a wildcard (*)\n\nA wildcard will match against its position and any lesser significant positions\n\n```swift\nVersion(\"14.7.*\") ⟺ Version(14, 7, .wildcard)\n\nVersion(1, .wildcard).contains(Version(1, 1, 101))             // 1.* contains 1.1.101\nVersion(6, 0, 0, .wildcard).contains(Version(6, 0, 0, 101))    // 6.0.0.* contains 6.0.0.101\n```\n### Once a wildcard is found, any lesser significant places are ignored.\n\n```swift\nVersion(1, .wildcard, 1, 101) ⟺ Version(1, .wildcard)                // 1.*.1.101 is equivalent to 1.*\n```\n## Creation\n\n### Simple\n\n```swift\nlet v1 = Version(1)                  // 1\nlet v2 = Version(2, 56)              // 2.56\nlet v3 = Version(15, 3, 4)           // 15.3.4\nlet v4 = Version(15, 3, 4, 10001)    // 15.3.4.10001\n\nassert(v4.major.value == 15)\nassert(v4.patch.value == 4)\n```\n\n### Wildcards\n\nA wildcard value is specified as `UInt.wildcard` during construction\n\n```swift\nlet w1 = Version(1, .wildcard)           // 1.*\nlet w2 = Version(1, 15, 9, .wildcard)    // 1.15.9.*\n```\n\n### Parsing from a string\n\n```swift\n// Version constructor throws if provided an incorrect version string\nlet v1   = try Version(\"10.2.3.*\")      // OK\nlet v1_e = try Version(\"10..2.3.*\")     // Throws VersionError.InvalidVersionString\nlet v2_e = try Version(\"1.2.0-rc.3\")    // Throws VersionError.InvalidVersionString\n\nlet v3   = try Version(\"15.4.3\")        // OK\nlet v3_e = try Version(\"15.a4.3\")       // returns nil\n```\n\n## Equality\n\nSimple\n\n```swift\ntry Version(\"4.5.6\") == Version(4,5,6)\ntry Version(\"12.4.0\") == Version(12,4)\n```\n\nA wildcard matches any value from the wildcard position onward\n\n```swift\nVersion(4,.wildcard) == Version(4,5,6)    // 4.* == 4.5.6\nVersion(4,5,6) == Version(4,.wildcard)    // 4.5.6 == 4.*\nVersion(4,5,6) == Version(4,5,.wildcard)  // 4.5.6 == 4.5.*\n```\n\n## Comparison\n\nThe version class supports the standard operators `\u003c`, `\u003e`, `==`, `!=`, `\u003e=`, `\u003c=`\n\n```swift\n// Basic comparison\n\nlet v0 = Version(10, 4)\nlet v1 = Version(10, 4, 4)\nassert(v1 \u003e= v0)             // v1 is a later version number\n\n// Wildcard comparison\n\nlet v3 = Version(10, 4, .wildcard)\nv3.contains(v0)              // 10.4.* contains the value 10.4\n\nlet v4 = Version(10, 5, .wildcard)\n!v4.contains(v0)              // 10.5.* DOES NOT contain the value 10.4\n```\n## Ranges\n\nYou can use the standard Swift range operators for version checks\n\n```swift\nlet range = Version(1,0) ..\u003c Version(1,2)\nXCTAssertTrue(range.contains(Version(1,1)))\n```\n\n### Closed Range Through\nA range up to **_and including_** the upper bound\n\n```swift\nlet range = Version(4) ... Version(5)\n   \nrange.contains(Version(4))       // YES\nrange.contains(Version(4,5,3))   // YES\nrange.contains(Version(5))       // YES\nrange.contains(Version(5,1))     // NO\n```\n\n### Closed Range Up To\n\nA range up to **_but not including_** the upper bound\n\n```swift\nlet rangeUpTo = Version(4) ..\u003c Version(5)\n\nrange.contains(Version(3,9,100))  // NO\nrange.contains(Version(4))        // YES\nrange.contains(Version(4,5,3))    // YES\nrange.contains(Version(5))        // NO\n```\n\n### Partial Range Support\n\n```swift\nlet rangeAfter = Version(1,2) ...                   // All version numbers AFTER and including 1.2\nassert(rangeAfter.contains(Version(1,2,0))\nassert(rangeAfter.contains(Version(3,2))\n\nlet rangeBeforeInclusive = ... Version(7,8,1)       // All version numbers BEFORE and including 7.8.1\nlet rangeBeforeNonInclusive = ..\u003c Version(7,8,1)    // All version numbers BEFORE not including 7.8.1\n```\n\n## Incrementer\n\nSimple increment support.\n\n```swift\nlet vv12 = Version(1,2)                 // Start with v1.2\n\nlet vv1201 = try vv12.increment(.build)    // Move to v1.2.0.1\nassert(vv1201 == Version(1,2,0,1))\n\nlet vv121 = try vv1201.increment(.patch)   // Move from v1.2.0.1 -\u003e v1.2.1\nassert(vv121 == Version(1,2,1))\n\nlet vv13 = try vv121.increment(.minor)     // Move from v1.2.1 -\u003e v1.3\nassert(vv13 == Version(1,3))\n\nlet vv2 = try vv13.increment(.major)       // Move from v1.3 -\u003e v2.0\nassert(vv2 == Version(2))\n```\n\n## Codable support\n\nVersion is fully codable, so you can use Version objects in your codable structs/classes.\n\nThe coded value is the string version of the version (eg. `\"15.3.*\"`) so that it's easily and clearly interpreted within your coded text.\n\n```swift\nlet v1 = Version(55, .wildcard)\nlet data1 = try JSONEncoder().encode(v1)\n// Data contains \"55.*\"\n\nlet v2 = Version(1,3,4,9)\nlet data2 = try JSONEncoder().encode(v1)\n// Data contains \"1.3.4.9\"\nlet v2rec = try JSONDecoder().decode(Version.self, from: data2)\nXCTAssertEqual(v2, v2rec)\n```\n\n# License\n\n```\nMIT License\n\nCopyright (c) 2024 Darren Ford\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fdsfversion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdagronf%2Fdsfversion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fdsfversion/lists"}