Files
2026-07-13 12:22:33 +08:00

99 lines
3.3 KiB
Swift

import AdaptiveReplayKit
import Foundation
enum ReplayPolicyName: String, CaseIterable, Sendable {
case adaptive
case adaptiveActivity = "adaptive-activity"
case fixed2Minutes = "fixed-2m"
case fixed5Minutes = "fixed-5m"
case fixed15Minutes = "fixed-15m"
case fixed30Minutes = "fixed-30m"
case manual
var policy: any ReplayPolicy {
switch self {
case .adaptive:
AdaptiveReplayPolicy()
case .adaptiveActivity:
CodingActivityAdaptivePolicy()
case .fixed2Minutes:
FixedIntervalPolicy(minutes: 2)
case .fixed5Minutes:
FixedIntervalPolicy(minutes: 5)
case .fixed15Minutes:
FixedIntervalPolicy(minutes: 15)
case .fixed30Minutes:
FixedIntervalPolicy(minutes: 30)
case .manual:
ManualPolicy()
}
}
static var expectedValues: String {
allCases.map(\.rawValue).joined(separator: ", ")
}
}
enum CLIArguments {
case run(
tracePath: String,
policyNames: [ReplayPolicyName],
jsonOutput: Bool,
gapGraceSeconds: TimeInterval?)
case help(exitCode: Int32)
case invalid(message: String)
static func parse(_ arguments: [String]) -> Self {
if arguments.contains("-h") || arguments.contains("--help") {
return .help(exitCode: EXIT_SUCCESS)
}
var tracePath: String?
var policyNames: [ReplayPolicyName] = []
var jsonOutput = false
var gapGraceSeconds: TimeInterval? = ReplayTraceSegmenter.defaultGraceSeconds
var index = 0
while index < arguments.count {
let argument = arguments[index]
switch argument {
case "--json":
jsonOutput = true
case "--raw-wall-clock":
gapGraceSeconds = nil
case "--gap-grace":
index += 1
guard index < arguments.count,
let seconds = TimeInterval(arguments[index]),
seconds >= 0,
seconds.isFinite
else { return .invalid(message: "--gap-grace requires non-negative finite seconds") }
gapGraceSeconds = seconds
case "--policy":
index += 1
guard index < arguments.count else { return .invalid(message: "--policy requires a value") }
let rawPolicyName = arguments[index]
guard let policyName = ReplayPolicyName(rawValue: rawPolicyName) else {
return .invalid(
message: "unknown policy '\(rawPolicyName)' (expected: \(ReplayPolicyName.expectedValues))")
}
policyNames.append(policyName)
default:
guard tracePath == nil else {
return .invalid(message: "unexpected argument '\(argument)'")
}
tracePath = argument
}
index += 1
}
guard let tracePath else {
return .help(exitCode: EXIT_FAILURE)
}
return .run(
tracePath: tracePath,
policyNames: policyNames.isEmpty ? ReplayPolicyName.allCases : policyNames,
jsonOutput: jsonOutput,
gapGraceSeconds: gapGraceSeconds)
}
}