encoding.ts ×19

Frontier kind: Code frontier

unlabeled · c_d8c6cf61caa8

108 tests · 6280 LOC · 32 files · introduces 0 tests · 421 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
19 ranges421 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
847 ranges6280 lines · 32 files · Browse complete extent
All tests (intent)
108 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 421 introduced LOC across 19 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/services/textfile/common/encoding.ts 421 introduced LOC · 19 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- encoding.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { Readable, ReadableStream, newWriteableStream, listenStream } from '../../../../base/common/stream.js';
7 > import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from '../../../../base/common/buffer.js';
8 > import { importAMDNodeModule } from '../../../../amdX.js';
9 > import { CancellationTokenSource } from '../../../../base/common/cancellation.js';
10 > import { coalesce } from '../../../../base/common/arrays.js';
11 >
12 > export const UTF8 = 'utf8';
13 > export const UTF8_with_bom = 'utf8bom';
14 > export const UTF16be = 'utf16be';
15 > export const UTF16le = 'utf16le';
16 >
17 > export type UTF_ENCODING = typeof UTF8 | typeof UTF8_with_bom | typeof UTF16be | typeof UTF16le;
18 >
19 > export function isUTFEncoding(encoding: string): encoding is UTF_ENCODING {
20 return [UTF8, UTF8_with_bom, UTF16be, UTF16le].some(utfEncoding => utfEncoding === encoding);
21 }
23 > export const UTF16be_BOM = [0xFE, 0xFF];
24 > export const UTF16le_BOM = [0xFF, 0xFE];
25 > export const UTF8_BOM = [0xEF, 0xBB, 0xBF];
26 >
27 > const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not
28 > const NO_ENCODING_GUESS_MIN_BYTES = 512; // when not auto guessing the encoding, small number of bytes are enough
29 > const AUTO_ENCODING_GUESS_MIN_BYTES = 512 * 8; // with auto guessing we want a lot more content to be read for guessing
30 > const AUTO_ENCODING_GUESS_MAX_BYTES = 512 * 128; // set an upper limit for the number of bytes we pass on to jschardet
31 >
32 > export interface IDecodeStreamOptions {
33 > acceptTextOnly: boolean;
34 > guessEncoding: boolean;
35 > candidateGuessEncodings: string[];
36 > minBytesRequiredForDetection?: number;
37 >
38 > overwriteEncoding(detectedEncoding: string | null): Promise<string>;
39 > }
40 >
41 > export interface IDecodeStreamResult {
42 > stream: ReadableStream<string>;
43 > detected: IDetectedEncodingResult;
44 > }
45 >
46 > export const enum DecodeStreamErrorKind {
47 >
48 > /**
49 > * Error indicating that the stream is binary even
50 > * though `acceptTextOnly` was specified.
51 > */
52 > STREAM_IS_BINARY = 1
53 > }
54 >
55 > export class DecodeStreamError extends Error {
56 >
57 > constructor(
58 message: string,
59 readonly decodeStreamErrorKind: DecodeStreamErrorKind
61 super(message);
62 }
63 > } encoding.ts
64 >
65 > export interface IDecoderStream {
66 > write(buffer: Uint8Array): string;
67 > end(): string | undefined;
68 > }
69 >
70 > class DecoderStream implements IDecoderStream {
71 >
72 > /**
73 > * This stream will only load iconv-lite lazily if the encoding
74 > * is not UTF-8. This ensures that for most common cases we do
75 > * not pay the price of loading the module from disk.
76 > *
77 > * We still need to be careful when converting UTF-8 to a string
78 > * though because we read the file in chunks of Buffer and thus
79 > * need to decode it via TextDecoder helper that is available
80 > * in browser and node.js environments.
81 > */
82 > static async create(encoding: string): Promise<DecoderStream> {
83 > let decoder: IDecoderStream | undefined = undefined;
84 > if (encoding !== UTF8) {
85 const iconv = await importAMDNodeModule<typeof import('@vscode/iconv-lite-umd')>('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js');
86 decoder = iconv.getDecoder(toNodeEncoding(encoding));
87 > } else { encoding.ts
88 const utf8TextDecoder = new TextDecoder();
89 decoder = {
102 };
103 }
104 > encoding.ts
105 > return new DecoderStream(decoder);
106 > }
107 >
108 > private constructor(private iconvLiteDecoder: IDecoderStream) { }
109 >
110 > write(buffer: Uint8Array): string {
111 return this.iconvLiteDecoder.write(buffer);
112 }
113 > encoding.ts
114 > end(): string | undefined {
115 return this.iconvLiteDecoder.end();
116 }
117 > } encoding.ts
118 >
119 > export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeStreamOptions): Promise<IDecodeStreamResult> {
120 const minBytesRequiredForDetection = options.minBytesRequiredForDetection ?? (options.guessEncoding ? AUTO_ENCODING_GUESS_MIN_BYTES : NO_ENCODING_GUESS_MIN_BYTES);
121
214 });
215 }
216 > encoding.ts
217 export async function toEncodeReadable(readable: Readable<string>, encoding: string, options?: { addBOM?: boolean }): Promise<VSBufferReadable> {
218 const iconv = await importAMDNodeModule<typeof import('@vscode/iconv-lite-umd')>('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js');
263 };
264 }
265 > encoding.ts
266 export async function encodingExists(encoding: string): Promise<boolean> {
267 const iconv = await importAMDNodeModule<typeof import('@vscode/iconv-lite-umd')>('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js');
269 return iconv.encodingExists(toNodeEncoding(encoding));
270 }
271 > encoding.ts
272 > export function toNodeEncoding(enc: string | null): string {
273 if (enc === UTF8_with_bom || enc === null) {
274 return UTF8; // iconv does not distinguish UTF 8 with or without BOM, so we need to help it
277 return enc;
278 }
279 > encoding.ts
280 > export function detectEncodingByBOMFromBuffer(buffer: VSBuffer | null, bytesRead: number): typeof UTF8_with_bom | typeof UTF16le | typeof UTF16be | null {
281 if (!buffer || bytesRead < UTF16be_BOM.length) {
282 return null;
309 return null;
310 }
311 > encoding.ts
312 > // we explicitly ignore a specific set of encodings from auto guessing
313 > // - ASCII: we never want this encoding (most UTF-8 files would happily detect as
314 > // ASCII files and then you could not type non-ASCII characters anymore)
315 > // - UTF-16: we have our own detection logic for UTF-16
316 > // - UTF-32: we do not support this encoding in VSCode
317 > const IGNORE_ENCODINGS = ['ascii', 'utf-16', 'utf-32'];
318 >
319 > /**
320 > * Guesses the encoding from buffer.
321 > */
322 async function guessEncodingByBuffer(buffer: VSBuffer, candidateGuessEncodings?: string[]): Promise<string | null> {
323 const jschardet = await importAMDNodeModule<typeof import('jschardet')>('jschardet', 'dist/jschardet.min.js');
357 return toIconvLiteEncoding(guessed.encoding);
358 }
359 > encoding.ts
360 > const JSCHARDET_TO_ICONV_ENCODINGS: { [name: string]: string } = {
361 > 'ibm866': 'cp866',
362 > 'big5': 'cp950'
363 > };
364 >
365 function normalizeEncoding(encodingName: string): string {
366 return encodingName.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
367 }
368 > encoding.ts
369 function toIconvLiteEncoding(encodingName: string): string {
370 const normalizedEncodingName = normalizeEncoding(encodingName);
373 return mapped || normalizedEncodingName;
374 }
375 > encoding.ts
376 function toJschardetEncoding(encodingName: string): string | undefined {
377 const normalizedEncodingName = normalizeEncoding(encodingName);
380 return mapped ? mapped.guessableName : undefined;
381 }
382 > encoding.ts
383 function encodeLatin1(buffer: Uint8Array): string {
384 let result = '';
389 return result;
390 }
391 > encoding.ts
392 > /**
393 > * The encodings that are allowed in a settings file don't match the canonical encoding labels specified by WHATWG.
394 > * See https://encoding.spec.whatwg.org/#names-and-labels
395 > * Iconv-lite strips all non-alphanumeric characters, but ripgrep doesn't. For backcompat, allow these labels.
396 > */
397 > export function toCanonicalName(enc: string): string {
398 switch (enc) {
399 case 'shiftjis':
427 }
428 }
429 > encoding.ts
430 > export interface IDetectedEncodingResult {
431 > encoding: string | null;
432 > seemsBinary: boolean;
433 > }
434 >
435 > export interface IReadResult {
436 > buffer: VSBuffer | null;
437 > bytesRead: number;
438 > }
439 >
440 > export function detectEncodingFromBuffer(readResult: IReadResult, autoGuessEncoding?: false, candidateGuessEncodings?: string[]): IDetectedEncodingResult;
441 > export function detectEncodingFromBuffer(readResult: IReadResult, autoGuessEncoding?: boolean, candidateGuessEncodings?: string[]): Promise<IDetectedEncodingResult>;
442 > export function detectEncodingFromBuffer({ buffer, bytesRead }: IReadResult, autoGuessEncoding?: boolean, candidateGuessEncodings?: string[]): Promise<IDetectedEncodingResult> | IDetectedEncodingResult {
443
444 // Always first check for BOM to find out about encoding
507 return { seemsBinary, encoding };
508 }
509 > encoding.ts
510 > type EncodingsMap = { [encoding: string]: { labelLong: string; labelShort: string; order: number; encodeOnly?: boolean; alias?: string; guessableName?: string } };
511 >
512 > export const SUPPORTED_ENCODINGS: EncodingsMap = {
513 > utf8: {
514 > labelLong: 'UTF-8',
515 > labelShort: 'UTF-8',
516 > order: 1,
517 > alias: 'utf8bom',
518 > guessableName: 'UTF-8'
519 > },
520 > utf8bom: {
521 > labelLong: 'UTF-8 with BOM',
522 > labelShort: 'UTF-8 with BOM',
523 > encodeOnly: true,
524 > order: 2,
525 > alias: 'utf8'
526 > },
527 > utf16le: {
528 > labelLong: 'UTF-16 LE',
529 > labelShort: 'UTF-16 LE',
530 > order: 3,
531 > guessableName: 'UTF-16LE'
532 > },
533 > utf16be: {
534 > labelLong: 'UTF-16 BE',
535 > labelShort: 'UTF-16 BE',
536 > order: 4,
537 > guessableName: 'UTF-16BE'
538 > },
539 > windows1252: {
540 > labelLong: 'Western (Windows 1252)',
541 > labelShort: 'Windows 1252',
542 > order: 5,
543 > guessableName: 'windows-1252'
544 > },
545 > iso88591: {
546 > labelLong: 'Western (ISO 8859-1)',
547 > labelShort: 'ISO 8859-1',
548 > order: 6
549 > },
550 > iso88593: {
551 > labelLong: 'Western (ISO 8859-3)',
552 > labelShort: 'ISO 8859-3',
553 > order: 7
554 > },
555 > iso885915: {
556 > labelLong: 'Western (ISO 8859-15)',
557 > labelShort: 'ISO 8859-15',
558 > order: 8
559 > },
560 > macroman: {
561 > labelLong: 'Western (Mac Roman)',
562 > labelShort: 'Mac Roman',
563 > order: 9
564 > },
565 > cp437: {
566 > labelLong: 'DOS (CP 437)',
567 > labelShort: 'CP437',
568 > order: 10
569 > },
570 > windows1256: {
571 > labelLong: 'Arabic (Windows 1256)',
572 > labelShort: 'Windows 1256',
573 > order: 11
574 > },
575 > iso88596: {
576 > labelLong: 'Arabic (ISO 8859-6)',
577 > labelShort: 'ISO 8859-6',
578 > order: 12
579 > },
580 > windows1257: {
581 > labelLong: 'Baltic (Windows 1257)',
582 > labelShort: 'Windows 1257',
583 > order: 13
584 > },
585 > iso88594: {
586 > labelLong: 'Baltic (ISO 8859-4)',
587 > labelShort: 'ISO 8859-4',
588 > order: 14
589 > },
590 > iso885914: {
591 > labelLong: 'Celtic (ISO 8859-14)',
592 > labelShort: 'ISO 8859-14',
593 > order: 15
594 > },
595 > windows1250: {
596 > labelLong: 'Central European (Windows 1250)',
597 > labelShort: 'Windows 1250',
598 > order: 16,
599 > guessableName: 'windows-1250'
600 > },
601 > iso88592: {
602 > labelLong: 'Central European (ISO 8859-2)',
603 > labelShort: 'ISO 8859-2',
604 > order: 17,
605 > guessableName: 'ISO-8859-2'
606 > },
607 > cp852: {
608 > labelLong: 'Central European (CP 852)',
609 > labelShort: 'CP 852',
610 > order: 18
611 > },
612 > windows1251: {
613 > labelLong: 'Cyrillic (Windows 1251)',
614 > labelShort: 'Windows 1251',
615 > order: 19,
616 > guessableName: 'windows-1251'
617 > },
618 > cp866: {
619 > labelLong: 'Cyrillic (CP 866)',
620 > labelShort: 'CP 866',
621 > order: 20,
622 > guessableName: 'IBM866'
623 > },
624 > cp1125: {
625 > labelLong: 'Cyrillic (CP 1125)',
626 > labelShort: 'CP 1125',
627 > order: 21,
628 > guessableName: 'IBM1125'
629 > },
630 > iso88595: {
631 > labelLong: 'Cyrillic (ISO 8859-5)',
632 > labelShort: 'ISO 8859-5',
633 > order: 22,
634 > guessableName: 'ISO-8859-5'
635 > },
636 > koi8r: {
637 > labelLong: 'Cyrillic (KOI8-R)',
638 > labelShort: 'KOI8-R',
639 > order: 23,
640 > guessableName: 'KOI8-R'
641 > },
642 > koi8u: {
643 > labelLong: 'Cyrillic (KOI8-U)',
644 > labelShort: 'KOI8-U',
645 > order: 24
646 > },
647 > iso885913: {
648 > labelLong: 'Estonian (ISO 8859-13)',
649 > labelShort: 'ISO 8859-13',
650 > order: 25
651 > },
652 > windows1253: {
653 > labelLong: 'Greek (Windows 1253)',
654 > labelShort: 'Windows 1253',
655 > order: 26,
656 > guessableName: 'windows-1253'
657 > },
658 > iso88597: {
659 > labelLong: 'Greek (ISO 8859-7)',
660 > labelShort: 'ISO 8859-7',
661 > order: 27,
662 > guessableName: 'ISO-8859-7'
663 > },
664 > windows1255: {
665 > labelLong: 'Hebrew (Windows 1255)',
666 > labelShort: 'Windows 1255',
667 > order: 28,
668 > guessableName: 'windows-1255'
669 > },
670 > iso88598: {
671 > labelLong: 'Hebrew (ISO 8859-8)',
672 > labelShort: 'ISO 8859-8',
673 > order: 29,
674 > guessableName: 'ISO-8859-8'
675 > },
676 > iso885910: {
677 > labelLong: 'Nordic (ISO 8859-10)',
678 > labelShort: 'ISO 8859-10',
679 > order: 30
680 > },
681 > iso885916: {
682 > labelLong: 'Romanian (ISO 8859-16)',
683 > labelShort: 'ISO 8859-16',
684 > order: 31
685 > },
686 > windows1254: {
687 > labelLong: 'Turkish (Windows 1254)',
688 > labelShort: 'Windows 1254',
689 > order: 32
690 > },
691 > iso88599: {
692 > labelLong: 'Turkish (ISO 8859-9)',
693 > labelShort: 'ISO 8859-9',
694 > order: 33
695 > },
696 > cp857: {
697 > labelLong: 'Turkish (CP 857)',
698 > labelShort: 'CP 857',
699 > order: 34
700 > },
701 > windows1258: {
702 > labelLong: 'Vietnamese (Windows 1258)',
703 > labelShort: 'Windows 1258',
704 > order: 35
705 > },
706 > gbk: {
707 > labelLong: 'Simplified Chinese (GBK)',
708 > labelShort: 'GBK',
709 > order: 36
710 > },
711 > gb18030: {
712 > labelLong: 'Simplified Chinese (GB18030)',
713 > labelShort: 'GB18030',
714 > order: 37
715 > },
716 > cp950: {
717 > labelLong: 'Traditional Chinese (Big5)',
718 > labelShort: 'Big5',
719 > order: 38,
720 > guessableName: 'Big5'
721 > },
722 > big5hkscs: {
723 > labelLong: 'Traditional Chinese (Big5-HKSCS)',
724 > labelShort: 'Big5-HKSCS',
725 > order: 39
726 > },
727 > shiftjis: {
728 > labelLong: 'Japanese (Shift JIS)',
729 > labelShort: 'Shift JIS',
730 > order: 40,
731 > guessableName: 'SHIFT_JIS'
732 > },
733 > eucjp: {
734 > labelLong: 'Japanese (EUC-JP)',
735 > labelShort: 'EUC-JP',
736 > order: 41,
737 > guessableName: 'EUC-JP'
738 > },
739 > euckr: {
740 > labelLong: 'Korean (EUC-KR)',
741 > labelShort: 'EUC-KR',
742 > order: 42,
743 > guessableName: 'EUC-KR'
744 > },
745 > windows874: {
746 > labelLong: 'Thai (Windows 874)',
747 > labelShort: 'Windows 874',
748 > order: 43
749 > },
750 > iso885911: {
751 > labelLong: 'Latin/Thai (ISO 8859-11)',
752 > labelShort: 'ISO 8859-11',
753 > order: 44
754 > },
755 > koi8ru: {
756 > labelLong: 'Cyrillic (KOI8-RU)',
757 > labelShort: 'KOI8-RU',
758 > order: 45
759 > },
760 > koi8t: {
761 > labelLong: 'Tajik (KOI8-T)',
762 > labelShort: 'KOI8-T',
763 > order: 46
764 > },
765 > gb2312: {
766 > labelLong: 'Simplified Chinese (GB 2312)',
767 > labelShort: 'GB 2312',
768 > order: 47,
769 > guessableName: 'GB2312'
770 > },
771 > cp865: {
772 > labelLong: 'Nordic DOS (CP 865)',
773 > labelShort: 'CP 865',
774 > order: 48
775 > },
776 > cp850: {
777 > labelLong: 'Western European DOS (CP 850)',
778 > labelShort: 'CP 850',
779 > order: 49
780 > }
781 > };
782 >
783 > export const GUESSABLE_ENCODINGS: EncodingsMap = (() => {
784 > const guessableEncodings: EncodingsMap = {};
785 > for (const encoding in SUPPORTED_ENCODINGS) {
786 > if (SUPPORTED_ENCODINGS[encoding].guessableName) {
787 > guessableEncodings[encoding] = SUPPORTED_ENCODINGS[encoding];
788 > }
789 > }
790 >
791 > return guessableEncodings;
792 > })();