decoder.js (1408B)
1 function con(b) { 2 if ((b & 0xc0) === 0x80) { 3 return b & 0x3f; 4 } else { 5 throw new Error("invalid UTF-8 encoding"); 6 } 7 } 8 9 function code(min, n) { 10 if (n < min || (0xd800 <= n && n < 0xe000) || n >= 0x10000) { 11 throw new Error("invalid UTF-8 encoding"); 12 } else { 13 return n; 14 } 15 } 16 17 export function decode(bytes) { 18 return _decode(bytes) 19 .map(x => String.fromCharCode(x)) 20 .join(""); 21 } 22 23 function _decode(bytes) { 24 if (bytes.length === 0) { 25 return []; 26 } 27 28 /** 29 * 1 byte 30 */ 31 { 32 const [b1, ...bs] = bytes; 33 34 if (b1 < 0x80) { 35 return [code(0x0, b1), ..._decode(bs)]; 36 } 37 38 if (b1 < 0xc0) { 39 throw new Error("invalid UTF-8 encoding"); 40 } 41 } 42 43 /** 44 * 2 bytes 45 */ 46 { 47 const [b1, b2, ...bs] = bytes; 48 49 if (b1 < 0xe0) { 50 return [code(0x80, ((b1 & 0x1f) << 6) + con(b2)), ..._decode(bs)]; 51 } 52 } 53 54 /** 55 * 3 bytes 56 */ 57 { 58 const [b1, b2, b3, ...bs] = bytes; 59 60 if (b1 < 0xf0) { 61 return [ 62 code(0x800, ((b1 & 0x0f) << 12) + (con(b2) << 6) + con(b3)), 63 ..._decode(bs) 64 ]; 65 } 66 } 67 68 /** 69 * 4 bytes 70 */ 71 { 72 const [b1, b2, b3, b4, ...bs] = bytes; 73 74 if (b1 < 0xf8) { 75 return [ 76 code( 77 0x10000, 78 ((((b1 & 0x07) << 18) + con(b2)) << 12) + (con(b3) << 6) + con(b4) 79 ), 80 ..._decode(bs) 81 ]; 82 } 83 } 84 85 throw new Error("invalid UTF-8 encoding"); 86 }