Skip to content
This repository was archived by the owner on Dec 15, 2024. It is now read-only.

Commit 6d550ad

Browse files
committed
Updated for Swift 5
1 parent 628daa9 commit 6d550ad

File tree

1 file changed

+68
-156
lines changed

1 file changed

+68
-156
lines changed

Sources/SwiftFoundation/URL.swift

100755100644
Lines changed: 68 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,177 +1,89 @@
1-
//
21
// URL.swift
32
// SwiftFoundation
43
//
54
// Created by Alsey Coleman Miller on 6/29/15.
65
// Copyright © 2015 PureSwift. All rights reserved.
76
//
87

9-
#if os(Linux) || XcodeLinux
10-
11-
/// Encapsulates the components of an URL.
12-
public struct URL: CustomStringConvertible {
13-
14-
// MARK: - Properties
15-
16-
public var scheme: String
17-
18-
public var user: String?
19-
20-
public var password: String?
21-
22-
/// The host URL subcomponent (e.g. domain name, IP address)
23-
public var host: String?
24-
25-
public var port: UInt?
26-
27-
public var path: String?
28-
29-
public var query: [(String, String)]?
30-
31-
/// The fragment URL component (the part after a # symbol)
32-
public var fragment: String?
33-
34-
// MARK: - Initialization
35-
36-
public init(scheme: String) {
37-
38-
self.scheme = scheme
8+
/**
9+
A URL is a type that can potentially contain the location of a resource on a remote server, the path of a local file on disk, or even an arbitrary piece of encoded data.
10+
11+
You can construct URLs and access their parts. For URLs that represent local files, you can also manipulate properties of those files directly, such as changing the file's last modification date. Finally, you can pass URLs to other APIs to retrieve the contents of those URLs. For example, you can use the URLSession classes to access the contents of remote resources, as described in URL Session Programming Guide.
12+
13+
URLs are the preferred way to refer to local files. Most objects that read data from or write data to a file have methods that accept a URL instead of a pathname as the file reference. For example, you can get the contents of a local file URL as `String` by calling `func init(contentsOf:encoding) throws`, or as a `Data` by calling `func init(contentsOf:options) throws`.
14+
*/
15+
public struct URL {
16+
17+
internal let stringValue: String
18+
19+
/// Initialize with string.
20+
///
21+
/// Returns `nil` if a `URL` cannot be formed with the string (for example, if the string contains characters that are illegal in a URL, or is an empty string).
22+
public init?(string: String) {
23+
// TODO: Validate URL string
24+
guard string.isEmpty == false
25+
else { return nil }
26+
self.init(string: string)
3927
}
4028

41-
/// Creates an instance from the string. String must be a valid URL.
42-
public init?(stringValue: String) {
43-
44-
// parse string
45-
46-
debugPrint("URL parsing from string is not implemented yet!")
47-
48-
return nil
29+
/// Returns the absolute string for the URL.
30+
public var absoluteString: String {
31+
return stringValue
4932
}
33+
}
34+
35+
// MARK: - Equatable
36+
37+
extension URL: Equatable {
5038

51-
// MARK: - Generated Properties
39+
public static func == (lhs: URL, rhs: URL) -> Bool {
40+
return lhs.stringValue == rhs.stringValue
41+
}
42+
}
43+
44+
// MARK: - Hashable
45+
46+
extension URL: Hashable {
5247

53-
/// Whether the URL components form a valid URL
54-
public var valid: Bool {
55-
56-
// validate scheme
57-
58-
// host must exist for port to be specified
59-
if port != nil { guard host != nil else { return false } }
60-
61-
// user and password must both be nil or non-nil
62-
guard !((user != nil || password != nil) && (user == nil || password == nil)) else { return false }
63-
64-
// query must have at least one item
65-
if query != nil { guard query!.count > 0 else { return false } }
66-
67-
return true
48+
public func hash(into hasher: inout Hasher) {
49+
stringValue.hash(into: &hasher)
6850
}
51+
}
52+
53+
// MARK: - CustomStringConvertible
54+
55+
extension URL: CustomStringConvertible {
6956

70-
/// Returns a valid URL string or ```nil```
71-
public var URLString: String? {
72-
73-
guard self.valid else { return nil }
74-
75-
var stringValue = scheme + "://"
76-
77-
if let user = user { stringValue += user }
78-
79-
if let password = password { stringValue += ":\(password)"}
80-
81-
if user != nil { stringValue += "@" }
82-
83-
if let host = host { stringValue += host }
84-
85-
if let port = port { stringValue += ":\(port)" }
86-
87-
if let path = path { stringValue += "/\(path)" }
88-
89-
if let query = query {
90-
91-
stringValue += "?"
92-
93-
for (index, queryItem) in query.enumerated() {
94-
95-
let (name, value) = queryItem
96-
97-
stringValue += name + "=" + value
98-
99-
if index != query.count - 1 {
100-
101-
stringValue += "&"
102-
}
103-
}
104-
}
105-
106-
if let fragment = fragment { stringValue += "#\(fragment)" }
107-
57+
public var description: String {
10858
return stringValue
10959
}
60+
}
61+
62+
// MARK: - CustomDebugStringConvertible
63+
64+
extension URL: CustomDebugStringConvertible {
11065

111-
public var description: String {
112-
113-
let separator = " "
114-
115-
var description = ""
116-
117-
if let URLString = URLString {
118-
119-
description += "URL: " + URLString + separator
120-
}
121-
122-
description += "Scheme: " + scheme
123-
124-
if let user = user {
125-
126-
description += separator + "User: " + user
127-
}
128-
129-
if let password = password {
130-
131-
description += separator + "Password: " + password
132-
}
133-
134-
if let host = host {
135-
136-
description += separator + "Host: " + host
137-
}
138-
139-
if let port = port {
140-
141-
description += separator + "Port: " + "\(port)"
142-
}
143-
144-
if let path = path {
145-
146-
description += separator + "Path: " + path
147-
}
148-
149-
if let query = query {
150-
151-
var stringValue = ""
152-
153-
for (index, queryItem) in query.enumerated() {
154-
155-
let (name, value) = queryItem
156-
157-
stringValue += name + "=" + value
158-
159-
if index != query.count - 1 {
160-
161-
stringValue += "&"
162-
}
163-
}
164-
165-
description += separator + "Query: " + stringValue
166-
}
167-
168-
if let fragment = fragment {
169-
170-
description += separator + "Fragment: " + fragment
171-
}
172-
66+
public var debugDescription: String {
17367
return description
17468
}
17569
}
17670

177-
#endif
71+
// MARK: - Codable
72+
73+
extension URL: Codable {
74+
75+
public init(from decoder: Decoder) throws {
76+
let container = try decoder.singleValueContainer()
77+
let string = try container.decode(String.self)
78+
guard let url = URL(string: string) else {
79+
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath,
80+
debugDescription: "Invalid URL string."))
81+
}
82+
self = url
83+
}
84+
85+
public func encode(to encoder: Encoder) throws {
86+
var container = encoder.singleValueContainer()
87+
try container.encode(stringValue)
88+
}
89+
}

0 commit comments

Comments
 (0)