Compile, then decode through the module. Pass platform before arch, and default both to the host rather than darwin/arm64.
72 lines
2.5 KiB
Swift
72 lines
2.5 KiB
Swift
import Foundation
|
|
|
|
public struct PatternMemoryDecoding: Sendable {
|
|
public let value: DecodedPattern
|
|
public let data: Data
|
|
}
|
|
|
|
public enum PatternMemoryError: LocalizedError {
|
|
case detached
|
|
|
|
public var errorDescription: String? {
|
|
switch self {
|
|
case .detached:
|
|
return "The session is not attached."
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Engine {
|
|
public static let largestPatternRead = 1 << 20
|
|
|
|
public func describePatternLibrary() async -> [[String: Any]] {
|
|
var described: [[String: Any]] = []
|
|
for source in patterns.sources {
|
|
var entry: [String: Any] = ["id": source.id, "name": source.name, "kind": source.kind == .library ? "library" : "pattern"]
|
|
if let summary = try? await patternDecoder.summary(of: source) {
|
|
entry.merge(summary.jsonObject) { _, new in new }
|
|
}
|
|
described.append(entry)
|
|
}
|
|
return described
|
|
}
|
|
|
|
public func decodePattern(
|
|
text: String, typeName: String, sessionID: UUID, address: UInt64, byteCount: Int
|
|
) async throws -> PatternMemoryDecoding {
|
|
guard let node = node(forSessionID: sessionID), let target = node.processInfo else {
|
|
throw PatternMemoryError.detached
|
|
}
|
|
var data = Data(try await node.readRemoteMemory(at: address, count: byteCount))
|
|
while true {
|
|
let value = try await patternDecoder.decode(
|
|
text: text, typeName: typeName, data: data, address: address, platform: target.platform, arch: target.arch)
|
|
guard value.truncated, data.count < Self.largestPatternRead,
|
|
let more = try? await node.readRemoteMemory(at: address, count: min(data.count * 2, Self.largestPatternRead))
|
|
else {
|
|
return PatternMemoryDecoding(value: value, data: data)
|
|
}
|
|
data = Data(more)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension PatternSummary {
|
|
public var jsonObject: [String: Any] {
|
|
var object: [String: Any] = [
|
|
"types": declaredTypes.map { type -> [String: Any] in
|
|
var entry: [String: Any] = ["name": type.name, "kind": "\(type.kind)"]
|
|
if let size = type.size {
|
|
entry["size"] = size
|
|
}
|
|
return entry
|
|
},
|
|
"diagnostics": diagnostics.map { ["line": $0.line + 1, "column": $0.character + 1, "message": $0.message] },
|
|
]
|
|
if let rootType {
|
|
object["root_type"] = rootType
|
|
}
|
|
return object
|
|
}
|
|
}
|