mirror of
https://github.com/morluto/rea
synced 2026-10-25 14:01:13 -04:00
refactor(go): parse module records through one byte contract
Parse the original unframed module bytes for every build-info result. Remove the duplicate text facade and string-source branch while retaining observed text, framed bytes, malformed lines, quoting and replacement semantics. Validation: 163 Go parser, image, provider and public CLI/MCP tests passed using local binary fixtures; build, static and documentation checks passed.
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
} from "../native/metadata/BinaryContainer.js";
|
||||
import { readBinaryContainer } from "../native/metadata/readBinaryContainer.js";
|
||||
import type { GoModuleMetadata } from "../domain/go/goBinary.js";
|
||||
import { parseGoModuleBytes, parseGoModuleText } from "./GoModuleText.js";
|
||||
import { parseGoModuleBytes } from "./GoModuleText.js";
|
||||
import {
|
||||
goBuildInfoSearch,
|
||||
type GoBuildInfoSearchRange,
|
||||
@@ -212,10 +212,7 @@ export const readGoBinaryImage = (bytes: Buffer): GoBinaryImage => {
|
||||
module_bytes_base64: module.bytes.toString("base64"),
|
||||
version_location: version.location,
|
||||
module_location: module.location,
|
||||
module:
|
||||
moduleText === null
|
||||
? parseGoModuleBytes(moduleBody)
|
||||
: parseGoModuleText(moduleText),
|
||||
module: parseGoModuleBytes(moduleBody),
|
||||
},
|
||||
...(sectionNamesLimitation === undefined
|
||||
? {}
|
||||
|
||||
+9
-24
@@ -117,25 +117,17 @@ interface ModuleSourceLine {
|
||||
readonly terminated: boolean;
|
||||
}
|
||||
|
||||
function* moduleSourceLines(
|
||||
source: string | Buffer,
|
||||
): Generator<ModuleSourceLine> {
|
||||
function* moduleSourceLines(source: Buffer): Generator<ModuleSourceLine> {
|
||||
let start = 0;
|
||||
while (start < source.length) {
|
||||
const newline =
|
||||
typeof source === "string"
|
||||
? source.indexOf("\n", start)
|
||||
: source.indexOf(10, start);
|
||||
const newline = source.indexOf(10, start);
|
||||
const end = newline < 0 ? source.length : newline;
|
||||
let line: string | Buffer;
|
||||
if (typeof source === "string") line = source.slice(start, end);
|
||||
else {
|
||||
const bytes = source.subarray(start, end);
|
||||
try {
|
||||
line = utf8.decode(bytes);
|
||||
} catch {
|
||||
line = bytes;
|
||||
}
|
||||
const bytes = source.subarray(start, end);
|
||||
try {
|
||||
line = utf8.decode(bytes);
|
||||
} catch {
|
||||
line = bytes;
|
||||
}
|
||||
yield { line, terminated: newline >= 0 };
|
||||
if (newline < 0) return;
|
||||
@@ -147,7 +139,8 @@ const modulePrefixes = ["mod\t", "dep\t", "=>\t"].map((prefix) =>
|
||||
Buffer.from(prefix),
|
||||
);
|
||||
|
||||
const parseModuleRecords = (source: string | Buffer): GoModuleMetadata => {
|
||||
/** Decode an unframed Go module body while retaining non-UTF-8 line bytes exactly. */
|
||||
export const parseGoModuleBytes = (source: Buffer): GoModuleMetadata => {
|
||||
let path: string | null = null;
|
||||
let main: GoModule | null = null;
|
||||
const dependencies: GoModule[] = [];
|
||||
@@ -216,11 +209,3 @@ const parseModuleRecords = (source: string | Buffer): GoModuleMetadata => {
|
||||
complete: unparsed_lines.length + unparsed_line_bytes_base64.length === 0,
|
||||
};
|
||||
};
|
||||
|
||||
/** Decode Go's module records while preserving unsupported/malformed source lines. */
|
||||
export const parseGoModuleText = (text: string): GoModuleMetadata =>
|
||||
parseModuleRecords(text);
|
||||
|
||||
/** Decode an unframed Go module body while retaining non-UTF-8 line bytes exactly. */
|
||||
export const parseGoModuleBytes = (bytes: Buffer): GoModuleMetadata =>
|
||||
parseModuleRecords(bytes);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
parseGoModuleBytes,
|
||||
parseGoModuleText,
|
||||
} from "../../../src/go/GoModuleText.js";
|
||||
import { parseGoModuleBytes } from "../../../src/go/GoModuleText.js";
|
||||
|
||||
describe("Go producer module text", () => {
|
||||
it("preserves local replacements, empty fields and ordered duplicate build settings", () => {
|
||||
const parsed = parseGoModuleText(
|
||||
"path\texample.invalid/app\nmod\texample.invalid/app\t(devel)\t\ndep\texample.invalid/lib\tv1.2.3\th1:bytes\n=>\t../local lib\t\t\nbuild\tGOOS=linux\nbuild\tGOOS=custom\nbuild\t__proto__=kept\n",
|
||||
const parsed = parseGoModuleBytes(
|
||||
Buffer.from(
|
||||
"path\texample.invalid/app\nmod\texample.invalid/app\t(devel)\t\ndep\texample.invalid/lib\tv1.2.3\th1:bytes\n=>\t../local lib\t\t\nbuild\tGOOS=linux\nbuild\tGOOS=custom\nbuild\t__proto__=kept\n",
|
||||
),
|
||||
);
|
||||
expect(parsed).toMatchObject({
|
||||
path: "example.invalid/app",
|
||||
@@ -39,7 +38,7 @@ describe("Go producer module text", () => {
|
||||
) +
|
||||
"\n" +
|
||||
"build\traw=`a\rb`\n";
|
||||
expect(parseGoModuleText(text)).toMatchObject({
|
||||
expect(parseGoModuleBytes(Buffer.from(text))).toMatchObject({
|
||||
settings: [
|
||||
{ key: "key=quoted", value: "\x07\x0béé☺🚀" },
|
||||
{ key: "raw", value: "ab" },
|
||||
@@ -51,7 +50,7 @@ describe("Go producer module text", () => {
|
||||
it("reports unparsed records and malformed escaped bytes while retaining observed fields", () => {
|
||||
const text =
|
||||
'path\tapp\nmod\tapp\t(devel)\nbuild\tbad="\\xff"\nfuture\tdata\nbuild\tGOARCH=amd64';
|
||||
expect(parseGoModuleText(text)).toMatchObject({
|
||||
expect(parseGoModuleBytes(Buffer.from(text))).toMatchObject({
|
||||
path: "app",
|
||||
main: { sum: null },
|
||||
settings: [],
|
||||
@@ -65,8 +64,8 @@ describe("Go producer module text", () => {
|
||||
});
|
||||
|
||||
it("does not attach a replacement after a malformed module declaration", () => {
|
||||
const parsed = parseGoModuleText(
|
||||
"dep\tfirst\tv1\ndep\tmalformed\n=>\tlocal\t\t\n",
|
||||
const parsed = parseGoModuleBytes(
|
||||
Buffer.from("dep\tfirst\tv1\ndep\tmalformed\n=>\tlocal\t\t\n"),
|
||||
);
|
||||
expect(parsed.dependencies).toEqual([
|
||||
{ path: "first", version: "v1", sum: null, replacement: null },
|
||||
@@ -76,8 +75,10 @@ describe("Go producer module text", () => {
|
||||
|
||||
it("preserves duplicate singleton declarations as unknown instead of silently overwriting", () => {
|
||||
expect(
|
||||
parseGoModuleText(
|
||||
"path\tfirst\npath\tsecond\nmod\tfirst\tv1\nmod\tsecond\tv2\n",
|
||||
parseGoModuleBytes(
|
||||
Buffer.from(
|
||||
"path\tfirst\npath\tsecond\nmod\tfirst\tv1\nmod\tsecond\tv2\n",
|
||||
),
|
||||
),
|
||||
).toMatchObject({
|
||||
path: "first",
|
||||
|
||||
Reference in New Issue
Block a user