Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Sources/HTTPClient/Base/PrettyStringConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
/// A helper protocol for customizing descriptions.
internal protocol PrettyStringConvertible {

/// A pretty string description.
var prettyDescription: String { get }
}
/// A pretty string description.
var prettyDescription: String { get }
}
52 changes: 26 additions & 26 deletions Sources/HTTPClient/Interface/HTTPBody+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import Foundation

extension HTTPBody {
/// Decodes the HTTP body as the specified type using the provided decoder.
/// - Parameters:
/// - type: The type to decode the HTTP body as.
/// - decoder: The decoder to use for decoding the HTTP body.
/// - Returns: The decoded value.
/// - Throws: An error if the HTTP body cannot be decoded.
public func decode<T: Decodable>(
as type: T.Type,
using decoder: JSONDecoder = JSONDecoder()
) async throws -> T {
let data = try await Data(collecting: self, upTo: .max)
return try decoder.decode(type, from: data)
}
/// Decodes the HTTP body as the specified type using the provided decoder.
/// - Parameters:
/// - type: The type to decode the HTTP body as.
/// - decoder: The decoder to use for decoding the HTTP body.
/// - Returns: The decoded value.
/// - Throws: An error if the HTTP body cannot be decoded.
public func decode<T: Decodable>(
as type: T.Type,
using decoder: JSONDecoder = JSONDecoder()
) async throws -> T {
let data = try await Data(collecting: self, upTo: .max)
return try decoder.decode(type, from: data)
}

/// Decodes the HTTP body as a JSON object.
/// - Returns: The decoded JSON object.
/// - Throws: An error if the HTTP body cannot be decoded as JSON.
public func json() async throws -> Any {
let data = try await Data(collecting: self, upTo: .max)
return try JSONSerialization.jsonObject(with: data)
}
/// Decodes the HTTP body as a JSON object.
/// - Returns: The decoded JSON object.
/// - Throws: An error if the HTTP body cannot be decoded as JSON.
public func json() async throws -> Any {
let data = try await Data(collecting: self, upTo: .max)
return try JSONSerialization.jsonObject(with: data)
}

/// Decodes the HTTP body as a string.
/// - Returns: The decoded string.
/// - Throws: An error if the HTTP body cannot be decoded as a string.
public func string() async throws -> String {
try await String(collecting: self, upTo: .max)
}
/// Decodes the HTTP body as a string.
/// - Returns: The decoded string.
/// - Throws: An error if the HTTP body cannot be decoded as a string.
public func string() async throws -> String {
try await String(collecting: self, upTo: .max)
}
}
40 changes: 40 additions & 0 deletions Sources/HTTPClient/Interface/HTTPBody+Progress.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Foundation

extension HTTPBody {
/// Tracks the progress of the body and calls the handler.
public func trackingProgress(handler: @escaping (Progress) -> Void) -> HTTPBody {
var totalBytesProcessed: Int64 = 0
let totalLength: Int64? =
switch self.length {
case .known(let length):
length
case .unknown:
nil
}

let sequence = self.map { chunk in
let chunkSize = Int64(chunk.count)
totalBytesProcessed += chunkSize

let progress = Progress(completed: totalBytesProcessed, total: totalLength)
handler(progress)
return chunk
}

return HTTPBody(sequence, length: self.length, iterationBehavior: self.iterationBehavior)
}
}

/// A progress object that tracks the progress of a body.
public struct Progress: Sendable, Hashable {
/// The number of bytes processed.
public let completed: Int64
/// The total number of bytes to process.
public let total: Int64?

/// The fraction of the body that has been processed.
public var fractionCompleted: Double? {
guard let total = total, total > 0 else { return nil }
return Double(completed) / Double(total)
}
}
Loading
Loading