Skip to content

Commit 36ce1da

Browse files
committed
support parse protobuf.
1 parent 4b10413 commit 36ce1da

File tree

3 files changed

+248
-3
lines changed

3 files changed

+248
-3
lines changed

package-lock.json

Lines changed: 161 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"@testing-library/react": "^9.5.0",
1111
"@testing-library/user-event": "^7.2.1",
1212
"codemirror": "^5.58.2",
13+
"protobufjs": "^7.5.4",
1314
"react": "^16.13.1",
1415
"react-codemirror2": "^7.1.0",
1516
"react-copy-to-clipboard": "^5.0.2",

src/components/JSONFormatter/JSONFormatter.jsx

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { UnControlled as CodeMirror } from 'react-codemirror2'
44
import SnappyJS from 'snappyjs'
55
import { Buffer } from "buffer";
66
import { decode, encode } from "@msgpack/msgpack";
7+
import { Reader } from "protobufjs";
78

89
const zlib = require('zlib');
910
require('codemirror/mode/javascript/javascript');
@@ -34,6 +35,73 @@ const prefixToTypeName = {
3435
GA: "Gate",
3536
};
3637

38+
// Helper function to parse protobuf buffer and extract field information
39+
function parseProtobufBuffer(buffer) {
40+
const reader = new Reader(buffer);
41+
const fields = {};
42+
43+
while (reader.pos < reader.len) {
44+
const tag = reader.uint32();
45+
const fieldNumber = tag >>> 3;
46+
const wireType = tag & 7;
47+
48+
let value;
49+
switch (wireType) {
50+
case 0: // Varint
51+
value = reader.uint64().toString();
52+
break;
53+
case 1: // 64-bit
54+
value = reader.fixed64().toString();
55+
break;
56+
case 2: // Length-delimited
57+
const bytes = reader.bytes();
58+
// Try to parse as string, fallback to hex
59+
try {
60+
value = new TextDecoder().decode(bytes);
61+
// If it contains non-printable characters, show as hex
62+
if (!/^[\x20-\x7E]*$/.test(value)) {
63+
value = Buffer.from(bytes).toString('hex');
64+
}
65+
} catch {
66+
value = Buffer.from(bytes).toString('hex');
67+
}
68+
break;
69+
case 3: // Start group (deprecated)
70+
value = "start_group";
71+
break;
72+
case 4: // End group (deprecated)
73+
value = "end_group";
74+
break;
75+
case 5: // 32-bit
76+
value = reader.fixed32();
77+
break;
78+
default:
79+
value = "unknown_wire_type";
80+
}
81+
82+
fields[`field_${fieldNumber}`] = {
83+
field_number: fieldNumber,
84+
wire_type: wireType,
85+
wire_type_name: getWireTypeName(wireType),
86+
value: value
87+
};
88+
}
89+
90+
return fields;
91+
}
92+
93+
function getWireTypeName(wireType) {
94+
const wireTypeNames = {
95+
0: "VARINT",
96+
1: "I64",
97+
2: "LEN",
98+
3: "SGROUP",
99+
4: "EGROUP",
100+
5: "I32"
101+
};
102+
return wireTypeNames[wireType] || "UNKNOWN";
103+
}
104+
37105
// Additional CodeMirror options can be found here: https://github.com/JedWatson/react-codemirror
38106
var inputOptions = {
39107
lineNumbers: true,
@@ -85,9 +153,24 @@ export class JSONFormatter extends Component {
85153
var base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
86154
var intRegex = /^[0-9]+$/;
87155
if (base64regex.test(input)) {
88-
var uncompressed = SnappyJS.uncompress(Buffer.from(input, 'base64'));
89-
let utf8decoder = new TextDecoder()
90-
jsonString = utf8decoder.decode(uncompressed);
156+
try {
157+
// First try snappy decompression
158+
var uncompressed = SnappyJS.uncompress(Buffer.from(input, 'base64'));
159+
let utf8decoder = new TextDecoder()
160+
jsonString = utf8decoder.decode(uncompressed);
161+
} catch (snappyError) {
162+
try {
163+
// If snappy fails, try protobuf parsing
164+
const protobufBuffer = Buffer.from(input, 'base64');
165+
const parsedProtobuf = parseProtobufBuffer(protobufBuffer);
166+
jsonString = JSON.stringify({
167+
type: "protobuf_message",
168+
fields: parsedProtobuf
169+
}, null, 4);
170+
} catch (protobufError) {
171+
throw new Error("Unable to parse as snappy-compressed or protobuf data: " + protobufError.message);
172+
}
173+
}
91174
}
92175
else if (intRegex.test(input)) {
93176
var intValue = parseInt(input, 10); // base 10

0 commit comments

Comments
 (0)