File: Version.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (73 lines) | stat: -rw-r--r-- 2,742 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2021 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See https://swift.org/LICENSE.txt for license information
 See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

/// An arbitrary-length version tuple.
public struct Version: Codable, RandomAccessCollection, ExpressibleByArrayLiteral, CustomStringConvertible, Equatable {
    private var elements: [Int]
    
    /// The start index of the version-components tuple.
    public var startIndex: Int {
        return elements.startIndex
    }
    /// The end index of the version-components tuple.
    public var endIndex: Int {
        return elements.endIndex
    }
    /// Returns the version component at the given index.
    public subscript(index: Int) -> Int {
        return elements[index]
    }
    /// Creates a new version with the given components.
    /// - Parameter elements: The components of a version, for example: 1, 0, 3.
    public init(arrayLiteral elements: Int...) {
        self.elements = elements
    }

    /// Creates a new version from the given string representation.
    /// - parameter versionString: A version as a string.
    /// - warning: Returns `nil` if the version string contains non-integer or
    ///   negative numeric components; for example the strings "1.2.3-beta6" and "1.-2.3"
    ///   are invalid inputs.
    public init?(versionString: String) {
        let stringComponents = versionString.components(separatedBy: ".")
        let intComponents = stringComponents.compactMap { Int($0) }
        guard intComponents.count == stringComponents.count,
            intComponents.count > 0 else {
            return nil
        }
        guard !intComponents.contains(where: { $0 < 0 }) else {
            return nil
        }
        self.elements = intComponents
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(description)
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let string = try container.decode(String.self)
        if let versionFromString = Version(versionString: string) {
            self = versionFromString
        } else {
            throw DecodingError.dataCorruptedError(
                in: container,
                debugDescription: "Failed to create Version from given string '\(string)'"
            )
        }
    }

    /// The string representation of the version.
    public var description: String {
        return elements.map(String.init).joined(separator: ".")
    }
}