-
Notifications
You must be signed in to change notification settings - Fork 96
/
FileURL.swift
70 lines (60 loc) · 2.12 KB
/
FileURL.swift
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
//
// Copyright 2024 Readium Foundation. All rights reserved.
// Use of this source code is governed by the BSD-style license
// available in the top-level LICENSE file of the project.
//
import Foundation
/// Represents an absolute URL with the special scheme `file`.
///
/// See https://url.spec.whatwg.org/#special-scheme
public struct FileURL: AbsoluteURL, Hashable {
public init?(url: URL) {
let url = url.standardizedFileURL
guard
let scheme = url.scheme.map(URLScheme.init(rawValue:)),
scheme == .file,
// We can't use `url.path`, see https://openradar.appspot.com/28357201
let path = URLComponents(url: url, resolvingAgainstBaseURL: true)?.path,
!path.isEmpty
else {
return nil
}
self.path = path
self.scheme = scheme
self.url = url
}
/// Creates a file URL from a percent-decoded absolute path.
public init?(path: String, isDirectory: Bool) {
guard path != "/", !path.isEmpty, path.hasPrefix("/") else {
return nil
}
self.init(url: URL(fileURLWithPath: path, isDirectory: isDirectory))
}
public let url: URL
public let path: String
public let scheme: URLScheme
public let origin: String? = nil
public var lastPathSegment: String {
url.lastPathComponent
}
/// Returns whether the given `url` is `self` or one of its descendants.
public func isParent(of other: FileURL) -> Bool {
path == other.path || other.path.hasPrefix(path.addingSuffix("/"))
}
/// Returns whether the file exists on the file system.
// FIXME: Async
public func exists() throws -> Bool {
try url.checkResourceIsReachable()
}
/// Returns whether the file is a directory.
// FIXME: Async
public func isDirectory() throws -> Bool {
try (url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) ?? false
}
}
public extension URLConvertible {
/// Returns a `FileURL` if the URL has a `file` scheme.
var fileURL: FileURL? {
(absoluteURL as? FileURL) ?? FileURL(url: anyURL.url)
}
}