refs #13856 Merge branch 'origin/13856-upload-component'
[arvados-workbench2.git] / src / services / collection-files-service / collection-manifest-parser.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { KeepManifestStream, KeepManifestStreamFile, KeepManifest } from "../../models/keep-manifest";
6
7 /**
8  * Documentation [http://doc.arvados.org/api/storage.html](http://doc.arvados.org/api/storage.html)
9  */
10 export const parseKeepManifestText: (text: string) => KeepManifestStream[] = (text: string) =>
11     text
12         .split(/\n/)
13         .filter(streamText => streamText.length > 0)
14         .map(parseKeepManifestStream);
15
16 /**
17  * Documentation [http://doc.arvados.org/api/storage.html](http://doc.arvados.org/api/storage.html)
18  */
19 export const parseKeepManifestStream = (stream: string): KeepManifestStream => {
20     const tokens = stream.split(' ');
21     return {
22         name: streamName(tokens),
23         locators: locators(tokens),
24         files: files(tokens)
25     };
26 };
27
28 export const stringifyKeepManifest = (manifest: KeepManifest) =>
29     manifest.map(stringifyKeepManifestStream).join('');
30
31 export const stringifyKeepManifestStream = (stream: KeepManifestStream) =>
32     `.${stream.name} ${stream.locators.join(' ')} ${stream.files.map(stringifyFile).join(' ')}\n`;
33
34 const FILE_LOCATOR_REGEXP = /^([0-9a-f]{32})\+([0-9]+)(\+[A-Z][-A-Za-z0-9@_]*)*$/;
35
36 const FILE_REGEXP = /([0-9]+):([0-9]+):(.*)/;
37
38 const streamName = (tokens: string[]) => tokens[0].slice(1);
39
40 const locators = (tokens: string[]) => tokens.filter(isFileLocator);
41
42 const files = (tokens: string[]) => tokens.filter(isFile).map(parseFile);
43
44 const isFileLocator = (token: string) => FILE_LOCATOR_REGEXP.test(token);
45
46 const isFile = (token: string) => FILE_REGEXP.test(token);
47
48 const parseFile = (token: string): KeepManifestStreamFile => {
49     const match = FILE_REGEXP.exec(token);
50     const [position, size, name] = match!.slice(1);
51     return { name, position, size: parseInt(size, 10) };
52 };
53
54 const stringifyFile = (file: KeepManifestStreamFile) =>
55     `${file.position}:${file.size}:${file.name}`;