import Foundation import TermindDomain public nonisolated enum LinuxProcessParser { public static func parse(_ source: String) throws -> MetricsProcessSample { var cpu: [UInt64] = [] var cores = 0 var pageSize: Double? var readingProcesses = false var processes: [MetricsProcessCounter] = [] var seen = Set() for line in source.split(separator: "\n") { if line == "__TERMIND_PROCESSES__" { readingProcesses = true continue } if line.hasPrefix("pagesize ") { pageSize = line.split(separator: " ").last.flatMap { Double($0) } continue } if !readingProcesses { let fields = line.split(whereSeparator: \.isWhitespace) if fields.first == "cpu" { cpu = fields.dropFirst().compactMap { UInt64($0) } } else if let key = fields.first, key.hasPrefix("cpu"), Int(key.dropFirst(3)) != nil { cores += 1 } continue } // comm is parenthesized and can contain spaces or closing parentheses. guard let left = line.firstIndex(of: "("), let right = line.lastIndex(of: ")"), left < right, let pid = Int(line[.. 21, let user = UInt64(fields[11]), let system = UInt64(fields[12]), let started = UInt64(fields[19]), let pages = Double(fields[21]), pages.isFinite, pages >= 0, user <= UInt64.max - system else { continue } var memory: Double? if let pageSize, pageSize.isFinite, pageSize > 0, (pages * pageSize).isFinite { memory = pages * pageSize } processes.append( MetricsProcessCounter( pid: pid, name: String(line[line.index(after: left)..= 8, cores > 0 else { throw MetricsReadError.output } return MetricsProcessSample(cpu: cpu, coreCount: cores, processes: processes) } }