encoding-transform.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import {Buffer} from 'node:buffer';
  2. import {StringDecoder} from 'node:string_decoder';
  3. import {isUint8Array, bufferToUint8Array} from '../utils/uint-array.js';
  4. /*
  5. When using binary encodings, add an internal generator that converts chunks from `Buffer` to `string` or `Uint8Array`.
  6. Chunks might be Buffer, Uint8Array or strings since:
  7. - `subprocess.stdout|stderr` emits Buffers
  8. - `subprocess.stdin.write()` accepts Buffer, Uint8Array or string
  9. - Previous generators might return Uint8Array or string
  10. However, those are converted to Buffer:
  11. - on writes: `Duplex.writable` `decodeStrings: true` default option
  12. - on reads: `Duplex.readable` `readableEncoding: null` default option
  13. */
  14. export const getEncodingTransformGenerator = (binary, encoding, skipped) => {
  15. if (skipped) {
  16. return;
  17. }
  18. if (binary) {
  19. return {transform: encodingUint8ArrayGenerator.bind(undefined, new TextEncoder())};
  20. }
  21. const stringDecoder = new StringDecoder(encoding);
  22. return {
  23. transform: encodingStringGenerator.bind(undefined, stringDecoder),
  24. final: encodingStringFinal.bind(undefined, stringDecoder),
  25. };
  26. };
  27. const encodingUint8ArrayGenerator = function * (textEncoder, chunk) {
  28. if (Buffer.isBuffer(chunk)) {
  29. yield bufferToUint8Array(chunk);
  30. } else if (typeof chunk === 'string') {
  31. yield textEncoder.encode(chunk);
  32. } else {
  33. yield chunk;
  34. }
  35. };
  36. const encodingStringGenerator = function * (stringDecoder, chunk) {
  37. yield isUint8Array(chunk) ? stringDecoder.write(chunk) : chunk;
  38. };
  39. const encodingStringFinal = function * (stringDecoder) {
  40. const lastChunk = stringDecoder.end();
  41. if (lastChunk !== '') {
  42. yield lastChunk;
  43. }
  44. };