diff --git a/Sources/MultipartFormData/Boundary.swift b/Sources/MultipartFormData/Boundary.swift index 251178f..ae9bc00 100644 --- a/Sources/MultipartFormData/Boundary.swift +++ b/Sources/MultipartFormData/Boundary.swift @@ -92,18 +92,19 @@ extension Boundary { } } -// MARK: - Debug +// MARK: - CustomDebugStringConvertible extension Boundary: CustomDebugStringConvertible { public var debugDescription: String { - return _value + return rawValue } } -// MARK: - Helpers +// MARK: - Data extension Boundary { - internal var _value: String { + /// The raw string representation of a boundary. + public var rawValue: String { return String(bytes: _asciiData, encoding: .ascii) ?? "" } } diff --git a/Sources/MultipartFormData/ContentType.swift b/Sources/MultipartFormData/ContentType.swift index 649f116..ab218ee 100644 --- a/Sources/MultipartFormData/ContentType.swift +++ b/Sources/MultipartFormData/ContentType.swift @@ -11,7 +11,7 @@ public struct ContentType: HTTPHeaderField { public static let name: String = "Content-Type" public var value: String { - return mediaType._text + return mediaType.rawValue } /// The media type (MIME type) of the content type. @@ -36,6 +36,6 @@ public struct ContentType: HTTPHeaderField { extension ContentType { internal init(boundary: Boundary) { self.mediaType = .multipartFormData - self.parameters = [HTTPHeaderParameter("boundary", value: boundary._value)] + self.parameters = [HTTPHeaderParameter("boundary", value: boundary.rawValue)] } } diff --git a/Sources/MultipartFormData/HTTPHeaderField.swift b/Sources/MultipartFormData/HTTPHeaderField.swift index 8be70e9..cbffd9f 100644 --- a/Sources/MultipartFormData/HTTPHeaderField.swift +++ b/Sources/MultipartFormData/HTTPHeaderField.swift @@ -24,30 +24,31 @@ public protocol HTTPHeaderField: Sendable, Hashable, CustomDebugStringConvertibl var parameters: [HTTPHeaderParameter] { get set } } -// MARK: - Debug +// MARK: - CustomDebugStringConvertible extension HTTPHeaderField { /// A textual representation of this instance, suitable for debugging. public var debugDescription: String { - return _text + return rawValue } } -// MARK: - Helpers +// MARK: - Data extension HTTPHeaderField { - internal var _value: String { - if parameters.isEmpty { - return value - } - return "\(value); \(parameters._text)" + /// The actual header field value resulting from ``value`` and ``parameters``. + public var parameterizedValue: String { + if parameters.isEmpty { return value } + return "\(value); \(parameters.rawValue)" } - internal var _text: String { - return "\(Self.name): \(_value)" + /// The raw string representation of a header field. + public var rawValue: String { + return "\(Self.name): \(parameterizedValue)" } - internal var _data: Data { - return Data(_text.utf8) + /// The data representation of a header field. + public var data: Data { + return Data(rawValue.utf8) } } diff --git a/Sources/MultipartFormData/HTTPHeaderParameter.swift b/Sources/MultipartFormData/HTTPHeaderParameter.swift index 7a0abe3..046d03d 100644 --- a/Sources/MultipartFormData/HTTPHeaderParameter.swift +++ b/Sources/MultipartFormData/HTTPHeaderParameter.swift @@ -24,24 +24,26 @@ public struct HTTPHeaderParameter: Sendable, Hashable { } } -// MARK: - Debug +// MARK: - CustomDebugStringConvertible extension HTTPHeaderParameter: CustomDebugStringConvertible { public var debugDescription: String { - return _text + return rawValue } } -// MARK: - Helpers +// MARK: - Data extension HTTPHeaderParameter { - internal var _text: String { + /// The raw string representation of a header parameter. + public var rawValue: String { return "\(name)=\"\(value)\"" } } extension Array { - internal var _text: String { - return map(\._text).joined(separator: "; ") + /// The raw string representation of multiple header parameters. + public var rawValue: String { + return map(\.rawValue).joined(separator: "; ") } } diff --git a/Sources/MultipartFormData/MediaType.swift b/Sources/MultipartFormData/MediaType.swift index 0ca30d3..428f1bd 100644 --- a/Sources/MultipartFormData/MediaType.swift +++ b/Sources/MultipartFormData/MediaType.swift @@ -87,23 +87,24 @@ extension UTType { /// - Parameter mediaType: The media type. /// - Parameter supertype: Another UTType instance that the resulting type must conform to; for example, UTTypeData. public init?(mediaType: MediaType, conformingTo supertype: UTType = .data) { - self.init(mimeType: mediaType._text, conformingTo: supertype) + self.init(mimeType: mediaType.rawValue, conformingTo: supertype) } } #endif -// MARK: - Debug +// MARK: - CustomDebugStringConvertible extension MediaType: CustomDebugStringConvertible { public var debugDescription: String { - return _text + return rawValue } } -// MARK: - Helpers +// MARK: - Data extension MediaType { - internal var _text: String { + /// The raw string representation of a media type. + public var rawValue: String { return "\(type)/\(subtype)" } } diff --git a/Sources/MultipartFormData/MultipartFormData.swift b/Sources/MultipartFormData/MultipartFormData.swift index f8dac25..7912ed1 100644 --- a/Sources/MultipartFormData/MultipartFormData.swift +++ b/Sources/MultipartFormData/MultipartFormData.swift @@ -116,7 +116,7 @@ extension MultipartFormData { /// This combines all the data from the subparts into one big data object. public var httpBody: Data { let bodyData: Data = body - .map { ._dash + boundary._asciiData + ._crlf + $0._data + ._crlf } + .map { ._dash + boundary._asciiData + ._crlf + $0.data + ._crlf } .reduce(Data(), +) return bodyData + ._dash + boundary._asciiData + ._dash + ._crlf } @@ -158,11 +158,11 @@ extension MultipartFormData { } } -// MARK: - Debug +// MARK: - CustomDebugStringConvertible extension MultipartFormData: CustomDebugStringConvertible { public var debugDescription: String { - let bytes: Data = contentType._data + ._crlf + ._crlf + httpBody + let bytes: Data = contentType.data + ._crlf + ._crlf + httpBody return String(bytes: bytes, encoding: .utf8) ?? "" } } diff --git a/Sources/MultipartFormData/Subpart.swift b/Sources/MultipartFormData/Subpart.swift index c88e7c7..992d0f1 100644 --- a/Sources/MultipartFormData/Subpart.swift +++ b/Sources/MultipartFormData/Subpart.swift @@ -76,19 +76,20 @@ extension Subpart { } } -// MARK: - Debug +// MARK: - CustomDebugStringConvertible extension Subpart: CustomDebugStringConvertible { public var debugDescription: String { - return String(bytes: _data, encoding: .utf8) ?? "" + return String(bytes: data, encoding: .utf8) ?? "" } } -// MARK: - Helpers +// MARK: - Data extension Subpart { - internal var _data: Data { - let contentTypeData: Data = contentType.map { $0._data + ._crlf } ?? Data() - return contentDisposition._data + ._crlf + contentTypeData + ._crlf + body + /// The data representation of a subpart. + public var data: Data { + let contentTypeData: Data = contentType.map { $0.data + ._crlf } ?? Data() + return contentDisposition.data + ._crlf + contentTypeData + ._crlf + body } } diff --git a/Sources/MultipartFormData/URLRequest+MultipartFormData.swift b/Sources/MultipartFormData/URLRequest+MultipartFormData.swift index 39099f9..fe72100 100644 --- a/Sources/MultipartFormData/URLRequest+MultipartFormData.swift +++ b/Sources/MultipartFormData/URLRequest+MultipartFormData.swift @@ -33,6 +33,6 @@ extension URLRequest { /// Updates the corresponding header field with a``HTTPHeaderField`` object. /// - Parameter headerField: The new header field object. public mutating func updateHeaderField(with headerField: Field) { - setValue(headerField._value, forHTTPHeaderField: Field.name) + setValue(headerField.parameterizedValue, forHTTPHeaderField: Field.name) } } diff --git a/Tests/MultipartFormDataTests/BoundaryTests.swift b/Tests/MultipartFormDataTests/BoundaryTests.swift index dd2c11e..3ed5247 100644 --- a/Tests/MultipartFormDataTests/BoundaryTests.swift +++ b/Tests/MultipartFormDataTests/BoundaryTests.swift @@ -45,7 +45,7 @@ final class BoundaryTests: XCTestCase { let randomBoundary = Boundary.random() let asciiString = String(data: randomBoundary._asciiData, encoding: .ascii) XCTAssertNotNil(asciiString) - XCTAssertEqual(asciiString, randomBoundary._value) + XCTAssertEqual(asciiString, randomBoundary.rawValue) } } diff --git a/Tests/MultipartFormDataTests/ContentDispositionTests.swift b/Tests/MultipartFormDataTests/ContentDispositionTests.swift index 227fd89..fd34b6a 100644 --- a/Tests/MultipartFormDataTests/ContentDispositionTests.swift +++ b/Tests/MultipartFormDataTests/ContentDispositionTests.swift @@ -39,6 +39,6 @@ final class ContentDispositionTests: XCTestCase { func testData() throws { let contentDisposition = ContentDisposition(name: "a", filename: "a") - XCTAssertEqual(contentDisposition._data, Data("Content-Disposition: form-data; name=\"a\"; filename=\"a\"".utf8)) + XCTAssertEqual(contentDisposition.data, Data("Content-Disposition: form-data; name=\"a\"; filename=\"a\"".utf8)) } } diff --git a/Tests/MultipartFormDataTests/ContentTypeTests.swift b/Tests/MultipartFormDataTests/ContentTypeTests.swift index 00afb3c..c38ff89 100644 --- a/Tests/MultipartFormDataTests/ContentTypeTests.swift +++ b/Tests/MultipartFormDataTests/ContentTypeTests.swift @@ -11,13 +11,11 @@ import XCTest final class ContentTypeTests: XCTestCase { func testBoundaryParameters() throws { let contentType = ContentType(boundary: try Boundary(uncheckedBoundary: "test")) - XCTAssertEqual(contentType.parameters[0], HTTPHeaderParameter("boundary", value: "test")) } func testData() { let contentType = ContentType(mediaType: .textPlain, parameters: [HTTPHeaderParameter("test", value: "a")]) - - XCTAssertEqual(contentType._data, Data("Content-Type: text/plain; test=\"a\"".utf8)) + XCTAssertEqual(contentType.data, Data("Content-Type: text/plain; test=\"a\"".utf8)) } } diff --git a/Tests/MultipartFormDataTests/HTTPHeaderParameterTests.swift b/Tests/MultipartFormDataTests/HTTPHeaderParameterTests.swift index be76ad0..717855e 100644 --- a/Tests/MultipartFormDataTests/HTTPHeaderParameterTests.swift +++ b/Tests/MultipartFormDataTests/HTTPHeaderParameterTests.swift @@ -9,23 +9,22 @@ import XCTest @testable import MultipartFormData final class HTTPHeaderParameterTests: XCTestCase { - func testArrayText() { + func testArrayRawValue() { let singleParameter = [ HTTPHeaderParameter("test", value: "a") ] - XCTAssertEqual(singleParameter._text, "test=\"a\"") + XCTAssertEqual(singleParameter.rawValue, "test=\"a\"") let parameters = [ HTTPHeaderParameter("test", value: "a"), HTTPHeaderParameter("test", value: "a"), HTTPHeaderParameter("test", value: "a"), ] - XCTAssertEqual(parameters._text, "test=\"a\"; test=\"a\"; test=\"a\"") + XCTAssertEqual(parameters.rawValue, "test=\"a\"; test=\"a\"; test=\"a\"") } func testDebugDescription() { let parameter = HTTPHeaderParameter("test", value: "a") - let expectedDescription = "test=\"a\"" XCTAssertEqual(parameter.debugDescription, expectedDescription) } diff --git a/Tests/MultipartFormDataTests/MediaTypeTests.swift b/Tests/MultipartFormDataTests/MediaTypeTests.swift index 1cde915..9bbaa23 100644 --- a/Tests/MultipartFormDataTests/MediaTypeTests.swift +++ b/Tests/MultipartFormDataTests/MediaTypeTests.swift @@ -12,14 +12,13 @@ import UniformTypeIdentifiers @testable import MultipartFormData final class MediaTypeTests: XCTestCase { - func testText() { + func testRawValue() { let mediaType = MediaType(type: "type", subtype: "subtype") - XCTAssertEqual(mediaType._text, "type/subtype") + XCTAssertEqual(mediaType.rawValue, "type/subtype") } func testDebugDescription() { let mediaType = MediaType(type: "type", subtype: "subtype") - let expectedDescription = "type/subtype" XCTAssertEqual(mediaType.debugDescription, expectedDescription) } @@ -29,14 +28,12 @@ final class MediaTypeTests: XCTestCase { func testFromUTTypeConversion() throws { let uniformType = try XCTUnwrap(UTType("public.comma-separated-values-text")) let mediaType = try XCTUnwrap(MediaType(uniformType: uniformType)) - XCTAssertEqual(mediaType, .textCsv) } @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) func testToUTTypeConversion() throws { let uniformType = try XCTUnwrap(UTType(mediaType: .applicationJson)) - XCTAssertEqual(uniformType.identifier, "public.json") } #endif diff --git a/Tests/MultipartFormDataTests/MultipartFormDataTests.swift b/Tests/MultipartFormDataTests/MultipartFormDataTests.swift index 4a89670..982a901 100644 --- a/Tests/MultipartFormDataTests/MultipartFormDataTests.swift +++ b/Tests/MultipartFormDataTests/MultipartFormDataTests.swift @@ -12,7 +12,7 @@ final class MultipartFormDataTests: XCTestCase { func testContentType() throws { let boundary = try Boundary(uncheckedBoundary: "test") let multipartFormData = MultipartFormData(boundary: boundary) - XCTAssertEqual(multipartFormData.contentType._data, Data("Content-Type: multipart/form-data; boundary=\"test\"".utf8)) + XCTAssertEqual(multipartFormData.contentType.data, Data("Content-Type: multipart/form-data; boundary=\"test\"".utf8)) } func testHTTPBodyGeneration() throws { diff --git a/Tests/MultipartFormDataTests/SubpartTests.swift b/Tests/MultipartFormDataTests/SubpartTests.swift index 8962458..c8e08b6 100644 --- a/Tests/MultipartFormDataTests/SubpartTests.swift +++ b/Tests/MultipartFormDataTests/SubpartTests.swift @@ -21,7 +21,7 @@ final class SubpartTests: XCTestCase { "", "a", ].joined(separator: "\r\n").utf8) - XCTAssertEqual(subpart._data, expectedData) + XCTAssertEqual(subpart.data, expectedData) } func testDebugDescription() {