diff --git a/Package.swift b/Package.swift index 3daf286f..11619715 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,7 @@ import PackageDescription let package = Package( name: "Yams", + platforms: [.iOS(.v13), .macOS(.v13), .tvOS(.v13), .watchOS(.v6)], products: [ .library(name: "Yams", targets: ["Yams"]) ], diff --git a/Package@swift-6.swift b/Package@swift-6.swift index 187cbffd..6027c398 100644 --- a/Package@swift-6.swift +++ b/Package@swift-6.swift @@ -3,6 +3,7 @@ import PackageDescription let package = Package( name: "Yams", + platforms: [.iOS(.v13), .macOS(.v13), .tvOS(.v13), .watchOS(.v6)], products: [ .library(name: "Yams", targets: ["Yams"]) ], diff --git a/README.md b/README.md index 484c53bb..c71a424d 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,11 @@ and a third one for a [Yams-native](#yamsnode) representation. `Data`. ```swift +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import Yams struct S: Codable { @@ -184,7 +188,11 @@ When Apple's Combine framework is available, `YAMLDecoder` conforms to the ```swift import Combine +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import Yams func fetchBook(from url: URL) -> AnyPublisher { diff --git a/Sources/Yams/Anchor.swift b/Sources/Yams/Anchor.swift index 80962aed..ad275f0e 100644 --- a/Sources/Yams/Anchor.swift +++ b/Sources/Yams/Anchor.swift @@ -5,13 +5,18 @@ // Created by Adora Lynch on 8/9/24. // Copyright (c) 2024 Yams. All rights reserved. +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A representation of a YAML tag see: https://yaml.org/spec/1.2.2/ /// Types interested in Encoding and Decoding Anchors should /// conform to YamlAnchorProviding and YamlAnchorCoding respectively. public final class Anchor: RawRepresentable, ExpressibleByStringLiteral, Codable, Hashable { +#if !canImport(FoundationEssentials) /// A CharacterSet containing only characters which are permitted by the underlying cyaml implementation public static let permittedCharacters = CharacterSet.lowercaseLetters .union(.uppercaseLetters) @@ -22,6 +27,15 @@ public final class Anchor: RawRepresentable, ExpressibleByStringLiteral, Codable public static func is_cyamlAlpha(_ string: String) -> Bool { Anchor.permittedCharacters.isSuperset(of: .init(charactersIn: string)) } +#else + /// An Set containing only characters which are permitted by the underlying cyaml implementation + public static let permittedCharacters = Set( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_") + + /// Returns true if and only if `string` contains only characters which are also in `permittedCharacters` + public static func is_cyamlAlpha(_ string: String) -> Bool { + Anchor.permittedCharacters.isSuperset(of: .init(string)) + } +#endif public let rawValue: String diff --git a/Sources/Yams/Constructor.swift b/Sources/Yams/Constructor.swift index c9949577..39ebb1c3 100644 --- a/Sources/Yams/Constructor.swift +++ b/Sources/Yams/Constructor.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// Constructors are used to translate `Node`s to Swift values. public final class Constructor { @@ -175,24 +179,19 @@ extension Date: ScalarConstructible { /// /// - returns: An instance of `Date`, if one was successfully extracted from the scalar. public static func construct(from scalar: Node.Scalar) -> Date? { - let range = NSRange(location: 0, length: scalar.string.utf16.count) - guard let result = timestampPattern.firstMatch(in: scalar.string, options: [], range: range), - result.range.location != NSNotFound else { + guard let result = try! timestampPattern.firstMatch(in: scalar.string) else { return nil } - let components = (1.. = pattern([ + "^(?[0-9][0-9][0-9][0-9])", // year + "-(?[0-9][0-9]?)", // month + "-(?[0-9][0-9]?)", // day "(?:(?:[Tt]|[ \\t]+)", - "([0-9][0-9]?)", // hour - ":([0-9][0-9])", // minute - ":([0-9][0-9])", // second - "(?:\\.([0-9]*))?", // fraction - "(?:[ \\t]*(Z|([-+])([0-9][0-9]?)", // tz_sign, tz_hour - "(?::([0-9][0-9]))?))?)?$" // tz_minute + "(?[0-9][0-9]?)", // hour + ":(?[0-9][0-9])", // minute + ":(?[0-9][0-9])", // second + "(?:\\.(?[0-9]*))?", // fraction + "(?:[ \\t]*(Z|(?[-+])(?[0-9][0-9]?)", // tz_sign, tz_hour + "(?::(?[0-9][0-9]))?))?)?$" // tz_minute ].joined() ) } @@ -394,6 +393,12 @@ extension String: ScalarConstructible { // MARK: - Types that can't conform to ScalarConstructible +#if !canImport(ObjectiveC) && canImport(FoundationEssentials) +public struct NSNull: Hashable { + public init() {} +} +#endif + extension NSNull/*: ScalarConstructible*/ { /// Construct an instance of `NSNull`, if possible, from the specified scalar. /// diff --git a/Sources/Yams/Decoder.swift b/Sources/Yams/Decoder.swift index e4d1792d..2f92d7fb 100644 --- a/Sources/Yams/Decoder.swift +++ b/Sources/Yams/Decoder.swift @@ -6,7 +6,11 @@ // Copyright (c) 2017 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// `Codable`-style `Decoder` that can be used to decode a `Decodable` type from a given `String` and optional /// user info mapping. Similar to `Foundation.JSONDecoder`. diff --git a/Sources/Yams/Emitter.swift b/Sources/Yams/Emitter.swift index 7e6358d1..19c3bdc9 100644 --- a/Sources/Yams/Emitter.swift +++ b/Sources/Yams/Emitter.swift @@ -15,7 +15,11 @@ internal import CYaml @_implementationOnly import CYaml #endif #endif +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// Produce a YAML string from objects. /// diff --git a/Sources/Yams/Node.swift b/Sources/Yams/Node.swift index c335ee79..c93fbf8d 100644 --- a/Sources/Yams/Node.swift +++ b/Sources/Yams/Node.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// YAML Node. public enum Node: Hashable { diff --git a/Sources/Yams/Parser.swift b/Sources/Yams/Parser.swift index 660403e8..54317f0a 100644 --- a/Sources/Yams/Parser.swift +++ b/Sources/Yams/Parser.swift @@ -16,7 +16,11 @@ internal import CYaml @_implementationOnly import CYaml #endif #endif +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// Parse all YAML documents in a String /// and produce corresponding Swift objects. diff --git a/Sources/Yams/Representer.swift b/Sources/Yams/Representer.swift index 76f9842b..8bfb8ad5 100644 --- a/Sources/Yams/Representer.swift +++ b/Sources/Yams/Representer.swift @@ -6,7 +6,11 @@ // Copyright (c) 2017 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif public extension Node { /// Initialize a `Node` with a value of `NodeRepresentable`. diff --git a/Sources/Yams/Resolver.swift b/Sources/Yams/Resolver.swift index ae6f31b2..b86d5d2b 100644 --- a/Sources/Yams/Resolver.swift +++ b/Sources/Yams/Resolver.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// Class used to resolve nodes to tags based on customizable rules. public final class Resolver: Sendable { @@ -14,9 +18,9 @@ public final class Resolver: Sendable { public struct Rule: Sendable { /// The tag name this rule applies to. public let tag: Tag.Name - fileprivate let regexp: NSRegularExpression + fileprivate let regexp: Regex /// The regex pattern used to resolve this rule. - public var pattern: String { return regexp.pattern } + public let pattern: String /// Create a rule with the specified tag name and regex pattern. /// @@ -26,7 +30,8 @@ public final class Resolver: Sendable { /// - throws: Throws an error if the regular expression pattern is invalid. public init(_ tag: Tag.Name, _ pattern: String) throws { self.tag = tag - self.regexp = try .init(pattern: pattern, options: []) + self.regexp = try .init(pattern) + self.pattern = pattern } } @@ -85,7 +90,10 @@ public final class Resolver: Sendable { } func resolveTag(from string: String) -> Tag.Name { - for rule in rules where rule.regexp.matches(in: string) { + let rule = rules.first { rule in + try! rule.regexp.firstMatch(in: string) != nil + } + if let rule { return rule.tag } return .str @@ -156,20 +164,16 @@ extension Resolver.Rule { // swiftlint:enable force_try } -func pattern(_ string: String) -> NSRegularExpression { +func pattern(_ string: String) -> Regex { do { - return try .init(pattern: string, options: []) + return try .init(string) } catch { fatalError("unreachable") } } -private extension NSRegularExpression { - func matches(in string: String) -> Bool { - let range = NSRange(location: 0, length: string.utf16.count) - if let match = firstMatch(in: string, options: [], range: range) { - return match.range.location != NSNotFound - } - return false - } -} +#if swift(>=6.0) +extension Regex: @retroactive @unchecked Sendable {} +#else +extension Regex: @unchecked Sendable {} +#endif diff --git a/Sources/Yams/String+Yams.swift b/Sources/Yams/String+Yams.swift index 0f44b2df..12ff8cd4 100644 --- a/Sources/Yams/String+Yams.swift +++ b/Sources/Yams/String+Yams.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif extension String { typealias LineNumberColumnAndContents = (lineNumber: Int, column: Int, contents: String) diff --git a/Sources/Yams/YamlError.swift b/Sources/Yams/YamlError.swift index 5ddaf239..7ad055f0 100644 --- a/Sources/Yams/YamlError.swift +++ b/Sources/Yams/YamlError.swift @@ -15,7 +15,11 @@ internal import CYaml @_implementationOnly import CYaml #endif #endif +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// Errors thrown by Yams APIs. public enum YamlError: Error { diff --git a/Tests/YamsTests/ConstructorTests.swift b/Tests/YamsTests/ConstructorTests.swift index e742401a..12964753 100644 --- a/Tests/YamsTests/ConstructorTests.swift +++ b/Tests/YamsTests/ConstructorTests.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest import Yams diff --git a/Tests/YamsTests/EncoderTests.swift b/Tests/YamsTests/EncoderTests.swift index c0ef06d8..ceac6862 100644 --- a/Tests/YamsTests/EncoderTests.swift +++ b/Tests/YamsTests/EncoderTests.swift @@ -6,7 +6,11 @@ // Copyright (c) 2017 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest import Yams diff --git a/Tests/YamsTests/NodeTests.swift b/Tests/YamsTests/NodeTests.swift index f82250f2..644a5af7 100644 --- a/Tests/YamsTests/NodeTests.swift +++ b/Tests/YamsTests/NodeTests.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest import Yams diff --git a/Tests/YamsTests/PerformanceTests.swift b/Tests/YamsTests/PerformanceTests.swift index 5aee8dd2..e00fe870 100644 --- a/Tests/YamsTests/PerformanceTests.swift +++ b/Tests/YamsTests/PerformanceTests.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest import Yams diff --git a/Tests/YamsTests/RepresenterTests.swift b/Tests/YamsTests/RepresenterTests.swift index 797f64cb..a752eddc 100644 --- a/Tests/YamsTests/RepresenterTests.swift +++ b/Tests/YamsTests/RepresenterTests.swift @@ -6,7 +6,11 @@ // Copyright (c) 2017 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest import Yams diff --git a/Tests/YamsTests/SpecTests.swift b/Tests/YamsTests/SpecTests.swift index 402ceb89..692bb568 100644 --- a/Tests/YamsTests/SpecTests.swift +++ b/Tests/YamsTests/SpecTests.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest import Yams diff --git a/Tests/YamsTests/TestHelper.swift b/Tests/YamsTests/TestHelper.swift index d52e259d..240d2ba3 100644 --- a/Tests/YamsTests/TestHelper.swift +++ b/Tests/YamsTests/TestHelper.swift @@ -6,7 +6,11 @@ // Copyright (c) 2016 Yams. All rights reserved. // +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif import XCTest private let gregorianCalendar = Calendar(identifier: .gregorian)