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 |