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.
		
		
		
		
		
			
		
			
				
					
					
						
							102 lines
						
					
					
						
							3.6 KiB
						
					
					
				
			
		
		
	
	
							102 lines
						
					
					
						
							3.6 KiB
						
					
					
				| import { EndOfStreamError } from 'peek-readable';
 | |
| import { Buffer } from 'node:buffer';
 | |
| /**
 | |
|  * Core tokenizer
 | |
|  */
 | |
| export class AbstractTokenizer {
 | |
|     constructor(fileInfo) {
 | |
|         /**
 | |
|          * Tokenizer-stream position
 | |
|          */
 | |
|         this.position = 0;
 | |
|         this.numBuffer = new Uint8Array(8);
 | |
|         this.fileInfo = fileInfo ? fileInfo : {};
 | |
|     }
 | |
|     /**
 | |
|      * Read a token from the tokenizer-stream
 | |
|      * @param token - The token to read
 | |
|      * @param position - If provided, the desired position in the tokenizer-stream
 | |
|      * @returns Promise with token data
 | |
|      */
 | |
|     async readToken(token, position = this.position) {
 | |
|         const uint8Array = Buffer.alloc(token.len);
 | |
|         const len = await this.readBuffer(uint8Array, { position });
 | |
|         if (len < token.len)
 | |
|             throw new EndOfStreamError();
 | |
|         return token.get(uint8Array, 0);
 | |
|     }
 | |
|     /**
 | |
|      * Peek a token from the tokenizer-stream.
 | |
|      * @param token - Token to peek from the tokenizer-stream.
 | |
|      * @param position - Offset where to begin reading within the file. If position is null, data will be read from the current file position.
 | |
|      * @returns Promise with token data
 | |
|      */
 | |
|     async peekToken(token, position = this.position) {
 | |
|         const uint8Array = Buffer.alloc(token.len);
 | |
|         const len = await this.peekBuffer(uint8Array, { position });
 | |
|         if (len < token.len)
 | |
|             throw new EndOfStreamError();
 | |
|         return token.get(uint8Array, 0);
 | |
|     }
 | |
|     /**
 | |
|      * Read a numeric token from the stream
 | |
|      * @param token - Numeric token
 | |
|      * @returns Promise with number
 | |
|      */
 | |
|     async readNumber(token) {
 | |
|         const len = await this.readBuffer(this.numBuffer, { length: token.len });
 | |
|         if (len < token.len)
 | |
|             throw new EndOfStreamError();
 | |
|         return token.get(this.numBuffer, 0);
 | |
|     }
 | |
|     /**
 | |
|      * Read a numeric token from the stream
 | |
|      * @param token - Numeric token
 | |
|      * @returns Promise with number
 | |
|      */
 | |
|     async peekNumber(token) {
 | |
|         const len = await this.peekBuffer(this.numBuffer, { length: token.len });
 | |
|         if (len < token.len)
 | |
|             throw new EndOfStreamError();
 | |
|         return token.get(this.numBuffer, 0);
 | |
|     }
 | |
|     /**
 | |
|      * Ignore number of bytes, advances the pointer in under tokenizer-stream.
 | |
|      * @param length - Number of bytes to ignore
 | |
|      * @return resolves the number of bytes ignored, equals length if this available, otherwise the number of bytes available
 | |
|      */
 | |
|     async ignore(length) {
 | |
|         if (this.fileInfo.size !== undefined) {
 | |
|             const bytesLeft = this.fileInfo.size - this.position;
 | |
|             if (length > bytesLeft) {
 | |
|                 this.position += bytesLeft;
 | |
|                 return bytesLeft;
 | |
|             }
 | |
|         }
 | |
|         this.position += length;
 | |
|         return length;
 | |
|     }
 | |
|     async close() {
 | |
|         // empty
 | |
|     }
 | |
|     normalizeOptions(uint8Array, options) {
 | |
|         if (options && options.position !== undefined && options.position < this.position) {
 | |
|             throw new Error('`options.position` must be equal or greater than `tokenizer.position`');
 | |
|         }
 | |
|         if (options) {
 | |
|             return {
 | |
|                 mayBeLess: options.mayBeLess === true,
 | |
|                 offset: options.offset ? options.offset : 0,
 | |
|                 length: options.length ? options.length : (uint8Array.length - (options.offset ? options.offset : 0)),
 | |
|                 position: options.position ? options.position : this.position
 | |
|             };
 | |
|         }
 | |
|         return {
 | |
|             mayBeLess: false,
 | |
|             offset: 0,
 | |
|             length: uint8Array.length,
 | |
|             position: this.position
 | |
|         };
 | |
|     }
 | |
| }
 |