From 1f5cc7ac33a8f134b007e1d91b9502a68a4693fc Mon Sep 17 00:00:00 2001 From: JP Simard Date: Fri, 9 Dec 2022 10:57:14 -0500 Subject: [PATCH] Remove Foundation dependency --- .bazelrc | 2 +- Package.swift | 11 +-- Sources/Yams/Constructor.swift | 142 +--------------------------- Sources/Yams/Decoder.swift | 63 +------------ Sources/Yams/Emitter.swift | 9 +- Sources/Yams/Mark.swift | 10 +- Sources/Yams/Node.swift | 22 ----- Sources/Yams/Parser.swift | 57 +----------- Sources/Yams/Representer.swift | 163 ++++----------------------------- Sources/Yams/Resolver.swift | 34 ++----- Sources/Yams/String+Yams.swift | 81 ---------------- Sources/Yams/YamlError.swift | 18 +--- Sources/yams-cli/main.swift | 44 ++++++++- 13 files changed, 91 insertions(+), 565 deletions(-) delete mode 100644 Sources/Yams/String+Yams.swift diff --git a/.bazelrc b/.bazelrc index 7a96259..d8706ef 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,3 +1,3 @@ -build --macos_minimum_os=10.9 +build --macos_minimum_os=13.0 build --repo_env=CC=clang test --test_output=errors diff --git a/Package.swift b/Package.swift index 511dfe7..3fc7d72 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.4 +// swift-tools-version:5.7 import PackageDescription let dependencies: [Package.Dependency] @@ -10,6 +10,7 @@ dependencies = [] let package = Package( name: "Yams", + platforms: [.macOS(.v13)], products: [ .library(name: "Yams", targets: ["Yams"]), .executable(name: "yams-cli", targets: ["yams-cli"]) @@ -29,14 +30,6 @@ let package = Package( name: "Yams", dependencies: ["CYaml"], exclude: ["CMakeLists.txt"] - ), - .testTarget( - name: "YamsTests", - dependencies: ["Yams"], - exclude: ["CMakeLists.txt"], - resources: [ - .copy("Fixtures/SourceKitten#289/debug.yaml"), - ] ) ] ) diff --git a/Sources/Yams/Constructor.swift b/Sources/Yams/Constructor.swift index 29aa3c5..6325bd7 100644 --- a/Sources/Yams/Constructor.swift +++ b/Sources/Yams/Constructor.swift @@ -6,8 +6,6 @@ // Copyright (c) 2016 Yams. All rights reserved. // -import Foundation - /// Constructors are used to translate `Node`s to Swift values. public final class Constructor { /// Maps `Tag.Name`s to `Node.Scalar`s. @@ -75,11 +73,7 @@ extension Constructor { // JSON Schema .bool: Bool.construct, .float: Double.construct, - .null: NSNull.construct, - .int: MemoryLayout.size == 8 ? Int.construct : { Int.construct(from: $0) ?? Int64.construct(from: $0) }, - // http://yaml.org/type/index.html - .binary: Data.construct, - .timestamp: Date.construct + .int: MemoryLayout.size == 8 ? Int.construct : { Int.construct(from: $0) ?? Int64.construct(from: $0) } ] /// The default `Tag.Name` to `Node.Mapping` map. @@ -115,19 +109,6 @@ public protocol ScalarConstructible { static func construct(from scalar: Node.Scalar) -> Self? } -// MARK: - ScalarConstructible UUID Conformance - -extension UUID: ScalarConstructible { - /// Construct an instance of `UUID`, if possible, from the specified scalar. - /// - /// - parameter scalar: The `Node.Scalar` from which to extract a value of type `UUID`, if possible. - /// - /// - returns: An instance of `UUID`, if one was successfully extracted from the scalar. - public static func construct(from scalar: Node.Scalar) -> UUID? { - return UUID(uuidString: scalar.string) - } -} - // MARK: - ScalarConstructible Bool Conformance extension Bool: ScalarConstructible { @@ -148,90 +129,6 @@ extension Bool: ScalarConstructible { } } -// MARK: - ScalarConstructible Data Conformance - -extension Data: ScalarConstructible { - /// Construct an instance of `Data`, if possible, from the specified scalar. - /// - /// - parameter scalar: The `Node.Scalar` from which to extract a value of type `Data`, if possible. - /// - /// - returns: An instance of `Data`, if one was successfully extracted from the scalar. - public static func construct(from scalar: Node.Scalar) -> Data? { - return Data(base64Encoded: scalar.string, options: .ignoreUnknownCharacters) - } -} - -// MARK: - ScalarConstructible Date Conformance - -extension Date: ScalarConstructible { - /// Construct an instance of `Date`, if possible, from the specified scalar. - /// - /// - parameter scalar: The `Node.Scalar` from which to extract a value of type `Date`, if possible. - /// - /// - 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 { - return nil - } - let components = (1.. NSNull? { - switch scalar.string { - case "", "~", "null", "Null", "NULL": - return NSNull() - default: - return nil - } - } -} - // MARK: Mapping extension Dictionary { @@ -484,19 +363,6 @@ extension Array { } } -private extension String { - func substring(with range: NSRange) -> Substring? { - guard range.location != NSNotFound else { return nil } - let utf16lowerBound = utf16.index(utf16.startIndex, offsetBy: range.location) - let utf16upperBound = utf16.index(utf16lowerBound, offsetBy: range.length) - guard let lowerBound = utf16lowerBound.samePosition(in: self), - let upperBound = utf16upperBound.samePosition(in: self) else { - fatalError("unreachable") - } - return self[lowerBound..(_ type: T.Type = T.self, - from yamlData: Data, - userInfo: [CodingUserInfoKey: Any] = [:]) throws -> T where T: Swift.Decodable { - guard let yamlString = String(data: yamlData, encoding: encoding.swiftStringEncoding) else { - throw YamlError.dataCouldNotBeDecoded(encoding: encoding.swiftStringEncoding) - } - - return try decode(type, from: yamlString, userInfo: userInfo) - } - /// Encoding public var encoding: Parser.Encoding } @@ -234,7 +213,7 @@ extension _Decoder: SingleValueDecodingContainer { // MARK: - Swift.SingleValueDecodingContainer Methods - func decodeNil() -> Bool { return node.null == NSNull() } + func decodeNil() -> Bool { return false } func decode(_ type: T.Type) throws -> T where T: Decodable & ScalarConstructible { return try construct(type) } func decode(_ type: T.Type) throws -> T where T: Decodable {return try construct(type) ?? type.init(from: self) } @@ -318,32 +297,6 @@ extension UInt16: ScalarConstructible {} // MARK: - ScalarConstructible UInt32 Conformance extension UInt32: ScalarConstructible {} -// MARK: - ScalarConstructible Decimal Conformance - -extension Decimal: ScalarConstructible { - /// Construct an instance of `Decimal`, if possible, from the specified scalar. - /// - /// - parameter scalar: The `Node.Scalar` from which to extract a value of type `Decimal`, if possible. - /// - /// - returns: An instance of `Decimal`, if one was successfully extracted from the scalar. - public static func construct(from scalar: Node.Scalar) -> Decimal? { - return Decimal(string: scalar.string) - } -} - -// MARK: - ScalarConstructible URL Conformance - -extension URL: ScalarConstructible { - /// Construct an instance of `URL`, if possible, from the specified scalar. - /// - /// - parameter scalar: The `Node.Scalar` from which to extract a value of type `URL`, if possible. - /// - /// - returns: An instance of `URL`, if one was successfully extracted from the scalar. - public static func construct(from scalar: Node.Scalar) -> URL? { - return URL(string: scalar.string) - } -} - // MARK: Decoder.mark extension Decoder { @@ -352,17 +305,3 @@ extension Decoder { return (self as? _Decoder)?.node.mark } } - -// MARK: TopLevelDecoder - -#if canImport(Combine) -import protocol Combine.TopLevelDecoder - -extension YAMLDecoder: TopLevelDecoder { - public typealias Input = Data - - public func decode(_ type: T.Type, from: Data) throws -> T where T: Decodable { - try decode(type, from: from, userInfo: [:]) - } -} -#endif diff --git a/Sources/Yams/Emitter.swift b/Sources/Yams/Emitter.swift index f2d0ffe..b223077 100644 --- a/Sources/Yams/Emitter.swift +++ b/Sources/Yams/Emitter.swift @@ -9,7 +9,6 @@ #if SWIFT_PACKAGE @_implementationOnly import CYaml #endif -import Foundation /// Produce a YAML string from objects. /// @@ -161,7 +160,7 @@ public func serialize( try emitter.open() try nodes.forEach(emitter.serialize) try emitter.close() - return String(data: emitter.data, encoding: .utf8)! + return emitter.data } /// Produce a YAML string from a `Node`. @@ -223,8 +222,8 @@ public final class Emitter { case crln } - /// Retrieve this Emitter's binary output. - public internal(set) var data = Data() + /// Retrieve this Emitter's string output. + public internal(set) var data = "" /// Configuration options to use when emitting YAML. public struct Options { @@ -304,7 +303,7 @@ public final class Emitter { yaml_emitter_set_output(&self.emitter, { pointer, buffer, size in guard let buffer = buffer else { return 0 } let emitter = unsafeBitCast(pointer, to: Emitter.self) - emitter.data.append(buffer, count: size) + emitter.data.append(String(cString: buffer)) return 1 }, unsafeBitCast(self, to: UnsafeMutableRawPointer.self)) diff --git a/Sources/Yams/Mark.swift b/Sources/Yams/Mark.swift index f8e992a..dea2541 100644 --- a/Sources/Yams/Mark.swift +++ b/Sources/Yams/Mark.swift @@ -26,14 +26,6 @@ extension Mark: CustomStringConvertible { extension Mark { /// Returns snippet string pointed by Mark instance from YAML String. public func snippet(from yaml: String) -> String { - let contents = yaml.substring(at: line - 1) - let columnIndex = contents.unicodeScalars - .index(contents.unicodeScalars.startIndex, - offsetBy: column - 1, - limitedBy: contents.unicodeScalars.endIndex)? - .samePosition(in: contents.utf16) ?? contents.utf16.endIndex - let columnInUTF16 = contents.utf16.distance(from: contents.utf16.startIndex, to: columnIndex) - return contents.endingWithNewLine + - String(repeating: " ", count: columnInUTF16) + "^" + fatalError("Unimplemented") } } diff --git a/Sources/Yams/Node.swift b/Sources/Yams/Node.swift index a5df8c0..87d69ef 100644 --- a/Sources/Yams/Node.swift +++ b/Sources/Yams/Node.swift @@ -6,8 +6,6 @@ // Copyright (c) 2016 Yams. All rights reserved. // -import Foundation - /// YAML Node. public enum Node: Hashable { /// Scalar node. @@ -92,31 +90,11 @@ extension Node { return scalar.flatMap(Double.construct) } - /// This node as an `NSNull`, if convertible. - public var null: NSNull? { - return scalar.flatMap(NSNull.construct) - } - /// This node as an `Int`, if convertible. public var int: Int? { return scalar.flatMap(Int.construct) } - /// This node as a `Data`, if convertible. - public var binary: Data? { - return scalar.flatMap(Data.construct) - } - - /// This node as a `Date`, if convertible. - public var timestamp: Date? { - return scalar.flatMap(Date.construct) - } - - /// This node as a `UUID`, if convertible. - public var uuid: UUID? { - return scalar.flatMap(UUID.construct) - } - // MARK: Typed accessor methods /// Returns this node mapped as an `Array`. If the node isn't a `Node.sequence`, the array will be diff --git a/Sources/Yams/Parser.swift b/Sources/Yams/Parser.swift index b96eb7f..4c2aa2c 100644 --- a/Sources/Yams/Parser.swift +++ b/Sources/Yams/Parser.swift @@ -9,7 +9,6 @@ #if SWIFT_PACKAGE @_implementationOnly import CYaml #endif -import Foundation /// Parse all YAML documents in a String /// and produce corresponding Swift objects. @@ -127,25 +126,8 @@ public final class Parser { /// This value is case insensitive. public static var `default`: Encoding = { let key = "YAMS_DEFAULT_ENCODING" - if let yamsEncoding = ProcessInfo.processInfo.environment[key], - let encoding = Encoding(rawValue: yamsEncoding.lowercased()) { - print(""" - `Parser.Encoding.default` was set to `\(encoding)` by the `\(key)` environment variable. - """) - return encoding - } return key.utf8.withContiguousStorageIfAvailable({ _ in true }) != nil ? .utf8 : .utf16 }() - - /// The equivalent `Swift.Encoding` value for `self`. - internal var swiftStringEncoding: String.Encoding { - switch self { - case .utf8: - return .utf8 - case .utf16: - return .utf16 - } - } } /// Encoding public let encoding: Encoding @@ -182,40 +164,10 @@ public final class Parser { try utf8Slice.withUnsafeBytes(startParse(with:)) } case .utf16: - // use native endianness - let isLittleEndian = 1 == 1.littleEndian - yaml_parser_set_encoding(&parser, isLittleEndian ? YAML_UTF16LE_ENCODING : YAML_UTF16BE_ENCODING) - let encoding: String.Encoding = isLittleEndian ? .utf16LittleEndian : .utf16BigEndian - let data = yaml.data(using: encoding)! - buffer = .utf16(data) - try data.withUnsafeBytes(startParse(with:)) + fatalError("Unimplemented") } } - /// Set up a `Parser` with a `Data` value as input. - /// - /// - parameter string: YAML Data encoded using the `encoding` encoding. - /// - parameter resolver: Resolver, `.default` if omitted. - /// - parameter constructor: Constructor, `.default` if omitted. - /// - parameter encoding: Encoding, `.default` if omitted. - /// - /// - throws: `YamlError`. - public convenience init(yaml data: Data, - resolver: Resolver = .default, - constructor: Constructor = .default, - encoding: Encoding = .default) throws { - guard let yamlString = String(data: data, encoding: encoding.swiftStringEncoding) else { - throw YamlError.dataCouldNotBeDecoded(encoding: encoding.swiftStringEncoding) - } - - try self.init( - yaml: yamlString, - resolver: resolver, - constructor: constructor, - encoding: encoding - ) - } - deinit { yaml_parser_delete(&parser) } @@ -258,7 +210,6 @@ public final class Parser { private enum Buffer { case utf8View(String.UTF8View) case utf8Slice(ArraySlice) - case utf16(Data) } private var buffer: Buffer } @@ -395,11 +346,7 @@ private class Event { return string(from: event.data.scalar.tag) } var scalarValue: String { - // scalar may contain NULL characters - let buffer = UnsafeBufferPointer(start: event.data.scalar.value, - count: event.data.scalar.length) - // libYAML converts scalar characters into UTF8 if input is other than YAML_UTF8_ENCODING - return String(bytes: buffer, encoding: .utf8)! + return String(cString: event.data.scalar.value) } // sequence diff --git a/Sources/Yams/Representer.swift b/Sources/Yams/Representer.swift index b4ff73c..1ee44c5 100644 --- a/Sources/Yams/Representer.swift +++ b/Sources/Yams/Representer.swift @@ -6,8 +6,6 @@ // Copyright (c) 2017 Yams. All rights reserved. // -import Foundation - #if os(iOS) || os(macOS) || os(watchOS) || os(tvOS) import Darwin private let cpow: (_: Double, _: Double) -> Double = Darwin.pow @@ -82,13 +80,6 @@ extension ScalarRepresentable { } } -extension NSNull: ScalarRepresentable { - /// This value's `Node.scalar` representation. - public func represented() -> Node.Scalar { - return .init("null", Tag(.null)) - } -} - extension Bool: ScalarRepresentable { /// This value's `Node.scalar` representation. public func represented() -> Node.Scalar { @@ -96,106 +87,36 @@ extension Bool: ScalarRepresentable { } } -extension Data: ScalarRepresentable { - /// This value's `Node.scalar` representation. - public func represented() -> Node.Scalar { - return .init(base64EncodedString(), Tag(.binary)) - } -} - -extension Date: ScalarRepresentable { - /// This value's `Node.scalar` representation. - public func represented() -> Node.Scalar { - return .init(iso8601String, Tag(.timestamp)) - } - - private var iso8601String: String { - let (integral, millisecond) = timeIntervalSinceReferenceDate.separateFractionalSecond(withPrecision: 3) - guard millisecond != 0 else { return iso8601Formatter.string(from: self) } - - let dateWithoutMillisecond = Date(timeIntervalSinceReferenceDate: integral) - return iso8601WithoutZFormatter.string(from: dateWithoutMillisecond) + - String(format: ".%03d", millisecond).trimmingCharacters(in: characterSetZero) + "Z" - } - - private var iso8601StringWithFullNanosecond: String { - let (integral, nanosecond) = timeIntervalSinceReferenceDate.separateFractionalSecond(withPrecision: 9) - guard nanosecond != 0 else { return iso8601Formatter.string(from: self) } - - let dateWithoutNanosecond = Date(timeIntervalSinceReferenceDate: integral) - return iso8601WithoutZFormatter.string(from: dateWithoutNanosecond) + - String(format: ".%09d", nanosecond).trimmingCharacters(in: characterSetZero) + "Z" - } -} - -private extension TimeInterval { - /// Separates the time interval into integral and fractional components, then rounds the `fractional` - /// component to `precision` number of digits. - /// - /// - returns: Tuple of integral part and converted fractional part - func separateFractionalSecond(withPrecision precision: Int) -> (integral: TimeInterval, fractional: Int) { - var integral = 0.0 - let fractional = modf(self, &integral) - - // TODO(TF-1203): Can't use `pow` free function due to - // https://bugs.swift.org/browse/TF-1203. - let radix = cpow(10.0, Double(precision)) - - let rounded = Int((fractional * radix).rounded()) - let quotient = rounded / Int(radix) - return quotient != 0 ? // carry-up? - (integral + TimeInterval(quotient), rounded % Int(radix)) : - (integral, rounded) - } -} - -private let characterSetZero = CharacterSet(charactersIn: "0") - -private let iso8601Formatter: DateFormatter = { - var formatter = DateFormatter() - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'" - formatter.timeZone = TimeZone(secondsFromGMT: 0) - return formatter -}() - -private let iso8601WithoutZFormatter: DateFormatter = { - var formatter = DateFormatter() - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss" - formatter.timeZone = TimeZone(secondsFromGMT: 0) - return formatter -}() - extension Double: ScalarRepresentable { /// This value's `Node.scalar` representation. public func represented() -> Node.Scalar { - return .init(doubleFormatter.string(for: self)!.replacingOccurrences(of: "+-", with: "-"), Tag(.float)) + if #available(macOS 13.0, *) { + return .init(doubleFormatter.string(for: self).replacing("+-", with: "-"), Tag(.float)) + } else { + fatalError("Unimplemented") + } } } extension Float: ScalarRepresentable { /// This value's `Node.scalar` representation. public func represented() -> Node.Scalar { - return .init(floatFormatter.string(for: self)!.replacingOccurrences(of: "+-", with: "-"), Tag(.float)) + if #available(macOS 13.0, *) { + return .init(floatFormatter.string(for: self).replacing("+-", with: "-"), Tag(.float)) + } else { + fatalError("Unimplemented") + } } } -private func numberFormatter(with significantDigits: Int) -> NumberFormatter { - let formatter = NumberFormatter() - formatter.locale = Locale(identifier: "en_US") - formatter.numberStyle = .scientific - formatter.usesSignificantDigits = true - formatter.maximumSignificantDigits = significantDigits - formatter.positiveInfinitySymbol = ".inf" - formatter.negativeInfinitySymbol = "-.inf" - formatter.notANumberSymbol = ".nan" - formatter.exponentSymbol = "e+" - return formatter -} +private let doubleFormatter = YamsNumberFormatter() +private let floatFormatter = YamsNumberFormatter() -private let doubleFormatter = numberFormatter(with: 15) -private let floatFormatter = numberFormatter(with: 7) +private struct YamsNumberFormatter { + func string(for number: some FloatingPoint) -> String { + "\(number)" + } +} // TODO: Support `Float80` //extension Float80: ScalarRepresentable {} @@ -230,20 +151,6 @@ extension Optional: NodeRepresentable { } } -extension Decimal: ScalarRepresentable { - /// This value's `Node.scalar` representation. - public func represented() -> Node.Scalar { - return .init(description) - } -} - -extension URL: ScalarRepresentable { - /// This value's `Node.scalar` representation. - public func represented() -> Node.Scalar { - return .init(absoluteString) - } -} - extension String: ScalarRepresentable { /// This value's `Node.scalar` representation. public func represented() -> Node.Scalar { @@ -252,13 +159,6 @@ extension String: ScalarRepresentable { } } -extension UUID: ScalarRepresentable { - /// This value's `Node.scalar` representation. - public func represented() -> Node.Scalar { - return .init(uuidString) - } -} - // MARK: - ScalarRepresentableCustomizedForCodable /// Types conforming to this protocol can be encoded by `YamlEncoder`. @@ -275,8 +175,6 @@ extension YAMLEncodable where Self: ScalarRepresentable { } extension Bool: YAMLEncodable {} -extension Data: YAMLEncodable {} -extension Decimal: YAMLEncodable {} extension Int: YAMLEncodable {} extension Int8: YAMLEncodable {} extension Int16: YAMLEncodable {} @@ -287,41 +185,18 @@ extension UInt8: YAMLEncodable {} extension UInt16: YAMLEncodable {} extension UInt32: YAMLEncodable {} extension UInt64: YAMLEncodable {} -extension URL: YAMLEncodable {} extension String: YAMLEncodable {} -extension UUID: YAMLEncodable {} - -extension Date: YAMLEncodable { - /// Returns this value wrapped in a `Node.scalar`. - public func box() -> Node { - return Node(iso8601StringWithFullNanosecond, Tag(.timestamp)) - } -} extension Double: YAMLEncodable { /// Returns this value wrapped in a `Node.scalar`. public func box() -> Node { - return Node(formattedStringForCodable, Tag(.float)) + return Node("\(self)", Tag(.float)) } } extension Float: YAMLEncodable { /// Returns this value wrapped in a `Node.scalar`. public func box() -> Node { - return Node(formattedStringForCodable, Tag(.float)) - } -} - -private extension FloatingPoint where Self: CVarArg { - var formattedStringForCodable: String { - // Since `NumberFormatter` creates a string with insufficient precision for Decode, - // it uses with `String(format:...)` - let string = String(format: "%.*g", DBL_DECIMAL_DIG, self) - // "%*.g" does not use scientific notation if the exponent is less than –4. - // So fallback to using `NumberFormatter` if string does not uses scientific notation. - guard string.lazy.suffix(5).contains("e") else { - return doubleFormatter.string(for: self)!.replacingOccurrences(of: "+-", with: "-") - } - return string + return Node("\(self)", Tag(.float)) } } diff --git a/Sources/Yams/Resolver.swift b/Sources/Yams/Resolver.swift index 40abb2d..3f7775c 100644 --- a/Sources/Yams/Resolver.swift +++ b/Sources/Yams/Resolver.swift @@ -6,17 +6,14 @@ // Copyright (c) 2016 Yams. All rights reserved. // -import Foundation - /// Class used to resolve nodes to tags based on customizable rules. public final class Resolver { /// Rule describing how to resolve tags from regex patterns. public struct Rule { /// The tag name this rule applies to. public let tag: Tag.Name - fileprivate let regexp: NSRegularExpression - /// The regex pattern used to resolve this rule. - public var pattern: String { return regexp.pattern } + private let _matches: (String) -> Bool + func matches(in string: String) -> Bool { _matches(string) } /// Create a rule with the specified tag name and regex pattern. /// @@ -26,7 +23,12 @@ public final class Resolver { /// - 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: []) + if #available(macOS 13.0, *) { + let regex = try Regex(pattern) + _matches = { $0.contains(regex) } + } else { + fatalError("Unimplemented") + } } } @@ -83,7 +85,7 @@ public final class Resolver { } func resolveTag(from string: String) -> Tag.Name { - for rule in rules where rule.regexp.matches(in: string) { + for rule in rules where rule.matches(in: string) { return rule.tag } return .str @@ -153,21 +155,3 @@ extension Resolver.Rule { // swiftlint:enable force_try } - -func pattern(_ string: String) -> NSRegularExpression { - do { - return try .init(pattern: string, options: []) - } 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 - } -} diff --git a/Sources/Yams/String+Yams.swift b/Sources/Yams/String+Yams.swift deleted file mode 100644 index 0f44b2d..0000000 --- a/Sources/Yams/String+Yams.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// String+Yams.swift -// Yams -// -// Created by Norio Nomura on 12/7/16. -// Copyright (c) 2016 Yams. All rights reserved. -// - -import Foundation - -extension String { - typealias LineNumberColumnAndContents = (lineNumber: Int, column: Int, contents: String) - - /// line number, column and contents at offset. - /// - /// - parameter offset: Int - /// - /// - returns: lineNumber: line number start from 0, - /// column: utf16 column start from 0, - /// contents: substring of line - func lineNumberColumnAndContents(at offset: Int) -> LineNumberColumnAndContents? { - return index(startIndex, offsetBy: offset, limitedBy: endIndex).flatMap(lineNumberColumnAndContents) - } - - /// line number, column and contents at Index. - /// - /// - parameter index: String.Index - /// - /// - returns: lineNumber: line number start from 0, - /// column: utf16 column start from 0, - /// contents: substring of line - func lineNumberColumnAndContents(at index: Index) -> LineNumberColumnAndContents { - assert((startIndex.. String { - var number = 0 - var outStartIndex = startIndex, outEndIndex = startIndex, outContentsEndIndex = startIndex - getLineStart(&outStartIndex, end: &outEndIndex, contentsEnd: &outContentsEndIndex, - for: startIndex..