You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					122 lines
				
				3.4 KiB
			
		
		
			
		
	
	
					122 lines
				
				3.4 KiB
			| 
											3 years ago
										 | const { end_of_stream } = require('../utils'); | ||
|  | const { label_to_encoding } = require('../table'); | ||
|  | 
 | ||
|  | class Stream { | ||
|  |   /** | ||
|  |    * A stream represents an ordered sequence of tokens. | ||
|  |    * @param {!(Array.<number>|Uint8Array)} tokens Array of tokens that provide | ||
|  |    * the stream. | ||
|  |    */ | ||
|  |   constructor(tokens) { | ||
|  |     this.tokens = [...tokens] | ||
|  |     // Reversed as push/pop is more efficient than shift/unshift.
 | ||
|  |     this.tokens.reverse() | ||
|  |   } | ||
|  |   /** | ||
|  |    * @returns True if end-of-stream has been hit. | ||
|  |    */ | ||
|  |   endOfStream() { | ||
|  |     return !this.tokens.length | ||
|  |   } | ||
|  |   /** | ||
|  |    * When a token is read from a stream, the first token in the | ||
|  |    * stream must be returned and subsequently removed, and | ||
|  |    * end-of-stream must be returned otherwise. | ||
|  |    * | ||
|  |    * @return Get the next token from the stream, or end_of_stream. | ||
|  |    */ | ||
|  |   read() { | ||
|  |     if (!this.tokens.length) | ||
|  |       return end_of_stream | ||
|  |     return this.tokens.pop() | ||
|  |   } | ||
|  |   /** | ||
|  |    * When one or more tokens are prepended to a stream, those tokens | ||
|  |    * must be inserted, in given order, before the first token in the | ||
|  |    * stream. | ||
|  |    * | ||
|  |    * @param {(number|!Array.<number>)} token The token(s) to prepend to the | ||
|  |    * stream. | ||
|  |    */ | ||
|  |   prepend(token) { | ||
|  |     if (Array.isArray(token)) { | ||
|  |       var tokens = /**@type {!Array.<number>}*/(token) | ||
|  |       while (tokens.length) | ||
|  |         this.tokens.push(tokens.pop()) | ||
|  |     } else { | ||
|  |       this.tokens.push(token) | ||
|  |     } | ||
|  |   } | ||
|  |   /** | ||
|  |    * When one or more tokens are pushed to a stream, those tokens | ||
|  |    * must be inserted, in given order, after the last token in the | ||
|  |    * stream. | ||
|  |    * | ||
|  |    * @param {(number|!Array.<number>)} token The tokens(s) to push to the | ||
|  |    * stream. | ||
|  |    */ | ||
|  |   push(token) { | ||
|  |     if (Array.isArray(token)) { | ||
|  |       const tokens = /**@type {!Array.<number>}*/(token) | ||
|  |       while (tokens.length) | ||
|  |         this.tokens.unshift(tokens.shift()) | ||
|  |     } else { | ||
|  |       this.tokens.unshift(token) | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | const DEFAULT_ENCODING = 'utf-8' | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns the encoding for the label. | ||
|  |  * @param {string} label The encoding label. | ||
|  |  */ | ||
|  | function getEncoding(label) { | ||
|  |   // 1. Remove any leading and trailing ASCII whitespace from label.
 | ||
|  |   label = String(label).trim().toLowerCase() | ||
|  | 
 | ||
|  |   // 2. If label is an ASCII case-insensitive match for any of the
 | ||
|  |   // labels listed in the table below, return the corresponding
 | ||
|  |   // encoding, and failure otherwise.
 | ||
|  |   if (Object.prototype.hasOwnProperty.call(label_to_encoding, label)) { | ||
|  |     return label_to_encoding[label] | ||
|  |   } | ||
|  |   return null | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //
 | ||
|  | // 5. Encodings
 | ||
|  | //
 | ||
|  | 
 | ||
|  | // 5.1 Encoders and decoders
 | ||
|  | 
 | ||
|  | // /** @interface */
 | ||
|  | // function Decoder() {}
 | ||
|  | // Decoder.prototype = {
 | ||
|  | //   /**
 | ||
|  | //    * @param {Stream} stream The stream of bytes being decoded.
 | ||
|  | //    * @param {number} bite The next byte read from the stream.
 | ||
|  | //    * @return {?(number|!Array.<number>)} The next code point(s)
 | ||
|  | //    *     decoded, or null if not enough data exists in the input
 | ||
|  | //    *     stream to decode a complete code point, or |finished|.
 | ||
|  | //    */
 | ||
|  | //   handler: function(stream, bite) {},
 | ||
|  | // }
 | ||
|  | 
 | ||
|  | // /** @interface */
 | ||
|  | // function Encoder() {}
 | ||
|  | // Encoder.prototype = {
 | ||
|  | //   /**
 | ||
|  | //    * @param {Stream} stream The stream of code points being encoded.
 | ||
|  | //    * @param {number} code_point Next code point read from the stream.
 | ||
|  | //    * @return {(number|!Array.<number>)} Byte(s) to emit, or |finished|.
 | ||
|  | //    */
 | ||
|  | //   handler: function(stream, code_point) {},
 | ||
|  | // }
 | ||
|  | 
 | ||
|  | module.exports = Stream | ||
|  | module.exports.DEFAULT_ENCODING = DEFAULT_ENCODING | ||
|  | module.exports.getEncoding = getEncoding |