Allow initialization from Substring etc.

This commit is contained in:
Max Howell
2019-03-06 12:54:41 -05:00
parent 02fd579f19
commit 8b371fa5d2
3 changed files with 35 additions and 22 deletions

View File

@@ -53,11 +53,25 @@ public struct Path: Equatable, Hashable, Comparable {
- Note: On macOS, removes an initial component of /private/var/automount, /var/automount, or /private from the path, if the result still indicates an existing file or directory (checked by consulting the file system).
- Returns: The path or `nil` if fed a relative path or a `~foo` string where there is no user `foo`.
*/
public init?(_ description: String) {
public init?<S: StringProtocol>(_ description: S) {
var pathComponents = description.split(separator: "/")
switch description.first {
case "/":
break
#if os(macOS)
func ifExists(withPrefix prefix: String, removeFirst n: Int) {
assert(prefix.split(separator: "/").count == n)
if description.hasPrefix(prefix), FileManager.default.fileExists(atPath: String(description)) {
pathComponents.removeFirst(n)
}
}
ifExists(withPrefix: "/private/var/automount", removeFirst: 3)
ifExists(withPrefix: "/var/automount", removeFirst: 2)
ifExists(withPrefix: "/private", removeFirst: 1)
#endif
self.string = join_(prefix: "/", pathComponents: pathComponents)
case "~":
if description == "~" {
self = Path.home
@@ -82,26 +96,11 @@ public struct Path: Equatable, Hashable, Comparable {
#endif
}
pathComponents.remove(at: 0)
pathComponents.insert(contentsOf: tilded.split(separator: "/"), at: 0)
self.string = join_(prefix: tilded, pathComponents: pathComponents)
default:
return nil
}
#if os(macOS)
func ifExists(withPrefix prefix: String, removeFirst n: Int) {
assert(prefix.split(separator: "/").count == n)
if description.hasPrefix(prefix), FileManager.default.fileExists(atPath: description) {
pathComponents.removeFirst(n)
}
}
ifExists(withPrefix: "/private/var/automount", removeFirst: 3)
ifExists(withPrefix: "/var/automount", removeFirst: 2)
ifExists(withPrefix: "/private", removeFirst: 1)
#endif
self.string = join_(prefix: "/", pathComponents: pathComponents)
}
/**

View File

@@ -594,4 +594,14 @@ class PathTests: XCTestCase {
XCTAssertEqual(Path.root.foo.bar.components, ["/", "foo", "bar"])
XCTAssertEqual(Path.root.components, ["/"])
}
func testFlatMap() throws {
// testing compile works
let foo: String? = "/a"
_ = foo.flatMap(Path.init)
let bar: Substring? = "/a"
_ = bar.flatMap(Path.init)
let baz: String.SubSequence? = "/a/b:1".split(separator: ":").first
_ = baz.flatMap(Path.init)
}
}

View File

@@ -1,7 +1,11 @@
#if !canImport(ObjectiveC)
import XCTest
extension PathTests {
static let __allTests = [
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__PathTests = [
("testBasename", testBasename),
("testBundleExtensions", testBundleExtensions),
("testCodable", testCodable),
@@ -19,6 +23,7 @@ extension PathTests {
("testFileHandleExtensions", testFileHandleExtensions),
("testFileReference", testFileReference),
("testFilesystemAttributes", testFilesystemAttributes),
("testFlatMap", testFlatMap),
("testInitializerForRelativePath", testInitializerForRelativePath),
("testIsDirectory", testIsDirectory),
("testJoin", testJoin),
@@ -48,10 +53,9 @@ extension PathTests {
]
}
#if !os(macOS)
public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(PathTests.__allTests),
testCase(PathTests.__allTests__PathTests),
]
}
#endif