Skip to content

Commit 59d3362

Browse files
committed
Add ASN.1 differ
1 parent f9fce48 commit 59d3362

33 files changed

+297
-15
lines changed

.vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
".editorconfig": true,
1414
".eslint*": true,
1515
".npmrc": true,
16-
".prettier*": true
16+
".prettier*": true,
17+
"out": true
1718
}
1819
}

electron.vite.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export default defineConfig({
1313
resolve: {
1414
alias: {
1515
'@renderer': resolve('src/renderer/src'),
16+
'@/components': resolve('src/renderer/src/components'),
1617
'@': resolve('src/')
1718
}
1819
},

resources/diff.pug

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//- Preprocessing
2+
each patch in patchList
3+
- patch.moduleName = patch.moduleName1 ? patch.moduleName1 : patch.moduleName2
4+
- patch.assignmentName = patch.assignmentName1 ? patch.assignmentName1 : patch.assignmentName2
5+
- patch.labelText = patch.change == 'modified' ? '±' : patch.change == 'added' ? '+' : patch.change == 'removed' ? '-' : ''
6+
7+
html
8+
head
9+
title Diff !{specOld}!{specNew}
10+
link(rel='stylesheet' type='text/css' href='https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css')
11+
link(rel='stylesheet' href='https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css')
12+
style.
13+
html. body {
14+
height: 100%;
15+
}
16+
/* Prevent contents goiong outside */
17+
.ui.grid {
18+
height: 100%;
19+
margin: 0;
20+
}
21+
aside, main {
22+
height: 100%;
23+
overflow-y: scroll;
24+
}
25+
/* Hide diff2html unnecessary part */
26+
.d2h-file-header {
27+
display: none;
28+
}
29+
30+
body
31+
div(class='ui grid')
32+
aside(class='four wide column')
33+
h1(class='ui header') !{specOld}!{specNew}
34+
ol(class='ui list')
35+
each patch in patchList
36+
li(value=patch.labelText)
37+
a(href='#'+patch.moduleName+'.'+patch.assignmentName) !{patch.assignmentName}
38+
39+
main(class='twelve wide column')
40+
each patch in patchList
41+
section(id=patch.moduleName+'.'+patch.assignmentName class=patch.change)
42+
h2(class='ui header')
43+
| !{patch.labelText}
44+
|
45+
if patch.change == 'modified'
46+
| !{patch.assignmentName1}
47+
div(class='ui label') !{patch.moduleName1}
48+
| → !{patch.assignmentName2}
49+
div(class='ui label') !{patch.moduleName2}
50+
else
51+
| !{patch.assignmentName}
52+
div(class='ui label') !{patch.moduleName}
53+
div !{patch.patchHtml}
54+
55+
div(class='column right aligned')
56+
| Powered by
57+
|
58+
a(href='https://github.com/3gpp-network/lib3rd') lib3rd
59+
| .
60+
|
61+
| Report an
62+
|
63+
a(href='https://github.com/3gpp-network/lib3rd/issues') issue

src/lib/message.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export const Channels = {
1515
IeListReport: z.literal('ieListReport'),
1616
FormatRequest: z.literal('formatRequest'),
1717
FormatReport: z.literal('formatReport'),
18+
DiffRequest: z.literal('diffRequest'),
19+
DiffReport: z.literal('diffReport'),
1820
SaveLocationRequest: z.literal('saveLocationRequest'),
1921
SaveLocationResponse: z.literal('saveLocationResponse'),
2022
OpenFolderRequest: z.literal('openFolderRequest'),
@@ -90,9 +92,26 @@ export const FormatReport = Message.merge(
9092
})
9193
)
9294

95+
export const DiffRequest = Message.merge(
96+
z.object({
97+
channel: Channels.DiffRequest,
98+
oldResourceId: z.string(),
99+
newResourceId: z.string()
100+
})
101+
)
102+
103+
export const DiffReport = Message.merge(
104+
z.object({
105+
channel: Channels.DiffReport,
106+
saveLocation: z.string().optional(),
107+
success: z.boolean()
108+
})
109+
)
110+
93111
export const SaveLocationRequest = Message.merge(
94112
z.object({
95-
channel: Channels.SaveLocationRequest
113+
channel: Channels.SaveLocationRequest,
114+
extension: z.enum(['xlsx', 'html'])
96115
})
97116
)
98117

src/main/globals.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
declare module '*?raw' {
2+
const content: string
3+
export default content
4+
}

src/main/index.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,18 @@ function createWindow(worker: Worker): void {
5252
if (messageParseResult.success) {
5353
const { dest, channel } = messageParseResult.data
5454
if (dest === 'main') {
55-
if (SaveLocationRequest.safeParse(msg).success) {
55+
const saveLocationRequestParseResult = SaveLocationRequest.safeParse(msg)
56+
if (saveLocationRequestParseResult.success) {
57+
const { extension } = saveLocationRequestParseResult.data
58+
const filetype =
59+
extension === 'xlsx' ? 'Spreadsheet file' : extension === 'html' ? 'Web page file' : ''
5660
const saveLocation = dialog.showSaveDialogSync({
57-
filters: [{ name: 'Spreadsheet file', extensions: ['xlsx'] }]
61+
filters: [{ name: filetype, extensions: [extension] }]
5862
})
5963
const saveLocationWithExtension =
60-
saveLocation && !saveLocation.endsWith('.xlsx') ? `${saveLocation}.xlsx` : saveLocation
64+
saveLocation && !saveLocation.endsWith(`.${extension}`)
65+
? `${saveLocation}.${extension}`
66+
: saveLocation
6167
worker.postMessage({
6268
src: 'main',
6369
dest: 'worker',

src/main/worker.ts

+63-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { parentPort as port, workerData as _workerData } from 'worker_threads'
22
import { z } from 'zod'
33
import {
4+
DiffReport,
5+
DiffRequest,
46
FormatReport,
57
FormatRequest,
68
IeListReport,
@@ -18,14 +20,18 @@ import { getHeapStatistics } from 'v8'
1820
import { debounce } from '../lib/debounce'
1921
import { Resource } from '../lib/resource'
2022
import { WorkerState } from '../lib/workerState'
23+
import { asn1 } from 'lib3rd'
24+
import diffTemplate from '../../resources/diff.pug?raw'
2125
import { Modules } from 'lib3rd/dist/asn1/classes/modules'
2226
import { Definitions } from 'lib3rd/dist/ran3/classes/definitions'
2327
import { Workbook } from 'exceljs'
2428
import { getWorkbook } from 'lib3rd/dist/common/spreadsheet'
2529
import { cloneDeep } from 'lodash'
30+
import { writeFileSync } from 'fs'
2631

2732
const resourceList: Resource[] = []
2833
let formatted: Workbook | undefined
34+
let renderedDiff: string | undefined
2935

3036
if (!port) {
3137
throw Error('Worker parent port error')
@@ -61,6 +67,16 @@ function reportFormatComplete(success: boolean, saveLocation: string | undefined
6167
} satisfies z.infer<typeof FormatReport>)
6268
}
6369

70+
function reportDiffComplete(success: boolean, saveLocation: string | undefined) {
71+
port?.postMessage({
72+
src: 'worker',
73+
dest: 'renderer',
74+
channel: 'diffReport',
75+
success,
76+
saveLocation
77+
} satisfies z.infer<typeof DiffReport>)
78+
}
79+
6480
function reportWorkerState(state: z.infer<typeof WorkerState>) {
6581
port?.postMessage({
6682
src: 'worker',
@@ -198,7 +214,40 @@ port.on('message', (msg: unknown) => {
198214
port?.postMessage({
199215
src: 'worker',
200216
dest: 'main',
201-
channel: 'saveLocationRequest'
217+
channel: 'saveLocationRequest',
218+
extension: 'xlsx'
219+
} satisfies z.infer<typeof SaveLocationRequest>)
220+
return
221+
}
222+
223+
const diffRequestParseResult = DiffRequest.safeParse(msg)
224+
if (diffRequestParseResult.success) {
225+
reportWorkerState('busy')
226+
const { oldResourceId, newResourceId } = diffRequestParseResult.data
227+
const oldResource = resourceList.find(({ id }) => id === oldResourceId)
228+
if (!(oldResource?.resource instanceof Modules)) {
229+
reportWorkerState('idle')
230+
return
231+
}
232+
const newResource = resourceList.find(({ id }) => id === newResourceId)
233+
if (!(newResource?.resource instanceof Modules)) {
234+
reportWorkerState('idle')
235+
return
236+
}
237+
const patchList = asn1.diff(oldResource.resource, newResource.resource)
238+
renderedDiff = asn1.renderDiff(
239+
{
240+
specOld: oldResource.name,
241+
specNew: newResource.name,
242+
patchList
243+
},
244+
diffTemplate
245+
)
246+
port?.postMessage({
247+
src: 'worker',
248+
dest: 'main',
249+
channel: 'saveLocationRequest',
250+
extension: 'html'
202251
} satisfies z.infer<typeof SaveLocationRequest>)
203252
return
204253
}
@@ -229,6 +278,19 @@ port.on('message', (msg: unknown) => {
229278
reportWorkerState('idle')
230279
})
231280
}
281+
if (renderedDiff) {
282+
try {
283+
writeFileSync(saveLocation, renderedDiff)
284+
reportDiffComplete(true, saveLocation)
285+
} catch (e) {
286+
reportDiffComplete(false, undefined)
287+
console.error(e)
288+
} finally {
289+
renderedDiff = undefined
290+
reportMemoryUsage()
291+
reportWorkerState('idle')
292+
}
293+
}
232294
return
233295
}
234296
})

src/renderer/src/App.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function App(): JSX.Element {
6464
{page === Page.FormatMessage && (
6565
<FormatMessage resourceList={resourceList} workerState={workerState} />
6666
)}
67-
{page === Page.DiffASN1 && <DiffAsn1 />}
67+
{page === Page.DiffASN1 && <DiffAsn1 resourceList={resourceList} workerState={workerState} />}
6868
<ResourceSheet
6969
open={openResourceSheet}
7070
onOpenChange={setOpenResourceSheet}

src/renderer/src/components/AboutDialog.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function AboutDialog({ open, onOpenChange }: Props) {
2626
<a href="https://github.com/proj3rd/tool3rd" target="_blank">
2727
GitHub
2828
</a>
29-
<a href="https://github.com/proj3rd/tool3rd/blob/main/CHANGELOG.md" target="_blank">
29+
<a href={`https://github.com/proj3rd/tool3rd/releases/tag/v${version}`} target="_blank">
3030
Changelog
3131
</a>
3232
<a href="https://github.com/proj3rd/tool3rd/releases" target="_blank">

src/renderer/src/components/Nav.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@ export function Nav({
8989
Format messsage
9090
</Button>
9191
</NavigationMenuItem>
92-
{/* <NavigationMenuItem>
92+
<NavigationMenuItem>
9393
<Button
9494
variant="ghost"
9595
onClick={selectPage(Page.DiffASN1)}
9696
disabled={workerState === 'busy'}
9797
>
9898
Diff ASN.1
9999
</Button>
100-
</NavigationMenuItem> */}
100+
</NavigationMenuItem>
101101
<NavigationMenuItem>
102102
<Button
103103
variant="ghost"
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)