mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-17 23:39:26 +02:00
Add bit count syntax to packet diagram
This commit is contained in:
@@ -30,6 +30,7 @@ describe('packet diagrams', () => {
|
||||
[
|
||||
[
|
||||
{
|
||||
"bits": 11,
|
||||
"end": 10,
|
||||
"label": "test",
|
||||
"start": 0,
|
||||
@@ -49,11 +50,13 @@ describe('packet diagrams', () => {
|
||||
[
|
||||
[
|
||||
{
|
||||
"bits": 11,
|
||||
"end": 10,
|
||||
"label": "test",
|
||||
"start": 0,
|
||||
},
|
||||
{
|
||||
"bits": 1,
|
||||
"end": 11,
|
||||
"label": "single",
|
||||
"start": 11,
|
||||
@@ -63,6 +66,58 @@ describe('packet diagrams', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle bit counts', async () => {
|
||||
const str = `packet-beta
|
||||
8bits: "byte"
|
||||
16bits: "word"
|
||||
`;
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getPacket()).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
{
|
||||
"bits": 8,
|
||||
"end": 7,
|
||||
"label": "byte",
|
||||
"start": 0,
|
||||
},
|
||||
{
|
||||
"bits": 16,
|
||||
"end": 23,
|
||||
"label": "word",
|
||||
"start": 8,
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle bit counts with bit or bits', async () => {
|
||||
const str = `packet-beta
|
||||
8bit: "byte"
|
||||
16bits: "word"
|
||||
`;
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getPacket()).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
{
|
||||
"bits": 8,
|
||||
"end": 7,
|
||||
"label": "byte",
|
||||
"start": 0,
|
||||
},
|
||||
{
|
||||
"bits": 16,
|
||||
"end": 23,
|
||||
"label": "word",
|
||||
"start": 8,
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should split into multiple rows', async () => {
|
||||
const str = `packet-beta
|
||||
0-10: "test"
|
||||
@@ -73,11 +128,13 @@ describe('packet diagrams', () => {
|
||||
[
|
||||
[
|
||||
{
|
||||
"bits": 11,
|
||||
"end": 10,
|
||||
"label": "test",
|
||||
"start": 0,
|
||||
},
|
||||
{
|
||||
"bits": 20,
|
||||
"end": 31,
|
||||
"label": "multiple",
|
||||
"start": 11,
|
||||
@@ -85,6 +142,7 @@ describe('packet diagrams', () => {
|
||||
],
|
||||
[
|
||||
{
|
||||
"bits": 31,
|
||||
"end": 63,
|
||||
"label": "multiple",
|
||||
"start": 32,
|
||||
@@ -92,6 +150,7 @@ describe('packet diagrams', () => {
|
||||
],
|
||||
[
|
||||
{
|
||||
"bits": 26,
|
||||
"end": 90,
|
||||
"label": "multiple",
|
||||
"start": 64,
|
||||
@@ -111,11 +170,13 @@ describe('packet diagrams', () => {
|
||||
[
|
||||
[
|
||||
{
|
||||
"bits": 17,
|
||||
"end": 16,
|
||||
"label": "test",
|
||||
"start": 0,
|
||||
},
|
||||
{
|
||||
"bits": 14,
|
||||
"end": 31,
|
||||
"label": "multiple",
|
||||
"start": 17,
|
||||
@@ -123,6 +184,7 @@ describe('packet diagrams', () => {
|
||||
],
|
||||
[
|
||||
{
|
||||
"bits": 31,
|
||||
"end": 63,
|
||||
"label": "multiple",
|
||||
"start": 32,
|
||||
@@ -142,6 +204,16 @@ describe('packet diagrams', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous with bit counts', async () => {
|
||||
const str = `packet-beta
|
||||
16bits: "test"
|
||||
18-20: "error"
|
||||
`;
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Packet block 18 - 20 is not contiguous. It should start from 16.]`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous for single packets', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
@@ -152,6 +224,16 @@ describe('packet diagrams', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous for single packets with bit counts', async () => {
|
||||
const str = `packet-beta
|
||||
16 bits: "test"
|
||||
18: "error"
|
||||
`;
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Packet block 18 - 18 is not contiguous. It should start from 16.]`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous for single packets - 2', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
@@ -172,4 +254,13 @@ describe('packet diagrams', () => {
|
||||
`[Error: Packet block 25 - 20 is invalid. End must be greater than start.]`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if bit count is 0', async () => {
|
||||
const str = `packet-beta
|
||||
0bits: "test"
|
||||
`;
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Packet block 0 is invalid. Cannot have a zero bit field.]`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -10,26 +10,39 @@ const maxPacketSize = 10_000;
|
||||
|
||||
const populate = (ast: Packet) => {
|
||||
populateCommonDb(ast, db);
|
||||
let lastByte = -1;
|
||||
let lastBit = -1;
|
||||
let word: PacketWord = [];
|
||||
let row = 1;
|
||||
const { bitsPerRow } = db.getConfig();
|
||||
for (let { start, end, label } of ast.blocks) {
|
||||
if (end && end < start) {
|
||||
|
||||
for (let { start, end, bits, label } of ast.blocks) {
|
||||
if (start !== undefined && end !== undefined && end < start) {
|
||||
throw new Error(`Packet block ${start} - ${end} is invalid. End must be greater than start.`);
|
||||
}
|
||||
if (start !== lastByte + 1) {
|
||||
if (start == undefined) {
|
||||
start = lastBit + 1;
|
||||
}
|
||||
if (start !== lastBit + 1) {
|
||||
throw new Error(
|
||||
`Packet block ${start} - ${end ?? start} is not contiguous. It should start from ${
|
||||
lastByte + 1
|
||||
lastBit + 1
|
||||
}.`
|
||||
);
|
||||
}
|
||||
lastByte = end ?? start;
|
||||
log.debug(`Packet block ${start} - ${lastByte} with label ${label}`);
|
||||
if (bits === 0) {
|
||||
throw new Error(`Packet block ${start} is invalid. Cannot have a zero bit field.`);
|
||||
}
|
||||
if (end == undefined) {
|
||||
end = start + (bits ?? 1) - 1;
|
||||
}
|
||||
if (bits == undefined) {
|
||||
bits = end - start + 1;
|
||||
}
|
||||
lastBit = end;
|
||||
log.debug(`Packet block ${start} - ${lastBit} with label ${label}`);
|
||||
|
||||
while (word.length <= bitsPerRow + 1 && db.getPacket().length < maxPacketSize) {
|
||||
const [block, nextBlock] = getNextFittingBlock({ start, end, label }, row, bitsPerRow);
|
||||
const [block, nextBlock] = getNextFittingBlock({ start, end, bits, label }, row, bitsPerRow);
|
||||
word.push(block);
|
||||
if (block.end + 1 === row * bitsPerRow) {
|
||||
db.pushWord(word);
|
||||
@@ -39,7 +52,7 @@ const populate = (ast: Packet) => {
|
||||
if (!nextBlock) {
|
||||
break;
|
||||
}
|
||||
({ start, end, label } = nextBlock);
|
||||
({ start, end, bits, label } = nextBlock);
|
||||
}
|
||||
}
|
||||
db.pushWord(word);
|
||||
@@ -50,9 +63,8 @@ const getNextFittingBlock = (
|
||||
row: number,
|
||||
bitsPerRow: number
|
||||
): [Required<PacketBlock>, PacketBlock | undefined] => {
|
||||
if (block.end === undefined) {
|
||||
block.end = block.start;
|
||||
}
|
||||
assert(block.start !== undefined, 'start should have been set during first phase');
|
||||
assert(block.end !== undefined, 'end should have been set during first phase');
|
||||
|
||||
if (block.start > block.end) {
|
||||
throw new Error(`Block start ${block.start} is greater than block end ${block.end}.`);
|
||||
@@ -62,16 +74,20 @@ const getNextFittingBlock = (
|
||||
return [block as Required<PacketBlock>, undefined];
|
||||
}
|
||||
|
||||
const rowEnd = row * bitsPerRow - 1;
|
||||
const rowStart = row * bitsPerRow;
|
||||
return [
|
||||
{
|
||||
start: block.start,
|
||||
end: row * bitsPerRow - 1,
|
||||
end: rowEnd,
|
||||
label: block.label,
|
||||
bits: rowEnd - block.start,
|
||||
},
|
||||
{
|
||||
start: row * bitsPerRow,
|
||||
start: rowStart,
|
||||
end: block.end,
|
||||
label: block.label,
|
||||
bits: block.end - rowStart,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
@@ -12,7 +12,12 @@ entry Packet:
|
||||
;
|
||||
|
||||
PacketBlock:
|
||||
start=INT('-' end=INT)? ':' label=STRING EOL
|
||||
(
|
||||
start=INT('-' (end=INT | bits=INT'bit''s'?))?
|
||||
| bits=INT'bit''s'?
|
||||
)
|
||||
':' label=STRING
|
||||
EOL
|
||||
;
|
||||
|
||||
terminal INT returns number: /0|[1-9][0-9]*/;
|
||||
|
Reference in New Issue
Block a user