Skip to content

Commit f2ddaab

Browse files
committed
feat: implement csv parser
This helps to reduce the volume Signed-off-by: Zxilly <zhouxinyu1001@gmail.com>
1 parent 7942999 commit f2ddaab

File tree

3 files changed

+62
-8
lines changed

3 files changed

+62
-8
lines changed

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
},
5555
"peerDependencies": {
5656
"picomatch": "^2.2.3",
57-
"csv-parse": "^4.15.3",
5857
"buffer": "^6.0.3"
5958
},
6059
"dependencies": {

src/util/util.ts

+60-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
// escapeAssertion escapes the dots in the assertion,
1616
// because the expression evaluation doesn't support such variable names.
1717

18-
import parse from 'csv-parse/lib/sync';
1918
import { RoleManager } from '../rbac';
2019

2120
function escapeAssertion(s: string): string {
@@ -157,11 +156,66 @@ function policyArrayToString(policy: string[]): string {
157156
}
158157

159158
function policyStringToArray(policy: string): string[][] {
160-
return parse(policy, {
161-
delimiter: ',',
162-
skip_empty_lines: true,
163-
trim: true,
164-
});
159+
const endCommaRe = /,$/;
160+
const quotaWrapperRe = /^".*"$/;
161+
162+
const lines: string[] = policy.split(/\r?\n/);
163+
const arrays: string[][] = [];
164+
165+
for (let line of lines) {
166+
const commentLabel = line.indexOf('#');
167+
if (commentLabel !== -1) {
168+
line = line.substr(0, commentLabel);
169+
}
170+
171+
line = line.trim();
172+
173+
if (endCommaRe.test(line)) {
174+
throw new Error('The csv standard does not allow a comma at the end of a sentence');
175+
}
176+
177+
const slices = line.split(',');
178+
let tokens: string[] = [];
179+
180+
for (let slice of slices) {
181+
slice = slice.trim();
182+
183+
// Remove parcel quotes
184+
if (quotaWrapperRe.test(slice)) {
185+
slice = slice.substr(1, slice.length - 2);
186+
}
187+
188+
if (slice.includes('""')) {
189+
// "" Escape processing
190+
const quotaSequence: number[] = [];
191+
192+
let pos = slice.indexOf('"');
193+
while (pos !== -1) {
194+
quotaSequence.push(pos);
195+
pos = slice.indexOf('"', pos + 1);
196+
}
197+
198+
if (quotaSequence.length % 2 !== 0) {
199+
throw new Error('Number of quotation marks does not match');
200+
}
201+
202+
for (let i = 0; i < quotaSequence.length; ) {
203+
if (quotaSequence[i] !== quotaSequence[i + 1] - 1) {
204+
throw new Error(`Unescaped " at ${line}`);
205+
}
206+
i += 2;
207+
}
208+
209+
slice = slice.replace(/""/g, '"');
210+
}
211+
212+
tokens.push(slice);
213+
}
214+
215+
arrays.push(deepCopy(tokens));
216+
tokens = [];
217+
}
218+
return arrays;
165219
}
166220

167221
function isRoleManagerSync(rm: RoleManager): boolean {

test/util.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ test('test getEvalValue', () => {
161161
});
162162

163163
test('test policyStringToArray', () => {
164-
expect(util.policyStringToArray('p,alice,data1,read')).toEqual([['p', 'alice', 'data1', 'read']]);
164+
expect(util.policyStringToArray('p,alice,data1,read#testtest')).toEqual([['p', 'alice', 'data1', 'read']]);
165+
expect(util.policyStringToArray('p,ali""ce,data1,read')).toEqual([['p', 'ali"ce', 'data1', 'read']]);
165166
expect(util.policyStringToArray(`"p","alice","data1","read"`)).toEqual([['p', 'alice', 'data1', 'read']]);
166167
expect(util.policyStringToArray(`"p"," alice","data1 ","read"`)).toEqual([['p', ' alice', 'data1 ', 'read']]);
167168
expect(util.policyStringToArray(`p,alice,data1,read\np,bob,data1,write`)).toEqual([

0 commit comments

Comments
 (0)