Tusker/Packages/Pachyderm/Sources/Pachyderm/Response/Pagination.swift

75 lines
2.3 KiB
Swift

//
// Pagination.swift
// Pachyderm
//
// Created by Shadowfacts on 9/9/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import Foundation
public struct Pagination: Sendable {
public let older: RequestRange?
public let newer: RequestRange?
}
extension Pagination {
init(string: String) {
let links = string.components(separatedBy: ",").compactMap(Item.init)
self.older = links.first(where: { $0.kind == .next })?.range
self.newer = links.first(where: { $0.kind == .prev })?.range
}
}
extension Pagination {
struct Item {
let kind: Kind
let id: String
let limit: Int?
var range: RequestRange {
switch kind {
case .next:
return .before(id: id, count: limit)
case .prev:
return .after(id: id, count: limit)
}
}
init?(string: String) {
let segments = string.components(separatedBy: .whitespaces).filter { !$0.isEmpty }.joined().components(separatedBy: ";")
let url = segments.first.flatMap { str in
String(str[str.index(after: str.startIndex)..<str.index(before: str.endIndex)])
}
let rel = segments.last?.replacingOccurrences(of: "\"", with: "").trimmingCharacters(in: .whitespaces).components(separatedBy: "=")
guard let validURL = url,
let key = rel?.first,
key == "rel",
let value = rel?.last,
let kind = Kind(rawValue: value),
let components = URLComponents(string: validURL),
let queryItems = components.queryItems else { return nil }
let min = queryItems.first { $0.name == "min_id" }?.value
let since = queryItems.first { $0.name == "since_id" }?.value
let max = queryItems.first { $0.name == "max_id" }?.value
guard let id = min ?? since ?? max else { return nil }
let limit = queryItems.first { $0.name == "limit" }.flatMap { $0.value }.flatMap { Int($0) }
self.kind = kind
self.id = id
self.limit = limit
}
}
}
extension Pagination.Item {
enum Kind: String {
case next, prev
}
}