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
						
					
					
				| 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 |