namespace AIStudio.Tools; /// /// The result of reading a file through the Rust runtime. /// /// /// Content and failure travel together on purpose. When reading a file returns a bare string, a /// failed extraction is indistinguishable from an empty document, and the empty document reaches /// the AI as if that were the content of the user's file. /// /// How the extraction ended. /// The extracted content. Empty when the extraction failed. /// Why the extraction failed or lost parts of the file. /// The technical failure description, meant for logs and diagnostics. /// The pages which could not be read, when known. /// The format the runtime identified by looking at the content, when it is worth naming. public readonly record struct FileExtractionResult(FileExtractionOutcome Outcome, string Content, FileExtractionErrorCode ErrorCode, string? ErrorMessage, IReadOnlyList FailedPages, string? DetectedFormat) { private static readonly int[] NO_FAILED_PAGES = []; public static FileExtractionResult Success(string content, string? detectedFormat = null) => new(FileExtractionOutcome.SUCCESS, content, FileExtractionErrorCode.NONE, null, NO_FAILED_PAGES, detectedFormat); public static FileExtractionResult Partial(string content, IReadOnlyList failedPages, string? detectedFormat = null) => new(FileExtractionOutcome.PARTIAL, content, FileExtractionErrorCode.PAGE_EXTRACTION_FAILED, null, failedPages, detectedFormat); public static FileExtractionResult Failed(FileExtractionErrorCode errorCode, string? errorMessage, string? detectedFormat = null) => new(FileExtractionOutcome.FAILED, string.Empty, errorCode, errorMessage, NO_FAILED_PAGES, detectedFormat); /// /// Gets a value indicating whether the whole file was read. /// public bool IsSuccess => this.Outcome is FileExtractionOutcome.SUCCESS; /// /// Gets a value indicating whether the content may be handed to the AI, i.e. the extraction /// either succeeded or lost only parts of the file. /// public bool HasUsableContent => this.Outcome is FileExtractionOutcome.SUCCESS or FileExtractionOutcome.PARTIAL; /// /// Gets a value indicating whether the file was read, but its content did not match its file /// extension. /// /// /// On a readable file, only the mismatch notice names a detected format, which is why no /// separate flag is needed here. /// public bool HasExtensionMismatch => this.HasUsableContent && this.DetectedFormat is not null; }