All files / src/utils encoder.ts

86.11% Statements 31/36
100% Branches 6/6
70% Functions 7/10
85.71% Lines 30/35
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 1137x 7x 7x                     7x   76x 76x     76x                 76x 73x   73x         73x           73x           73x             76x 72x             76x 59x           76x               76x 73x             76x             76x         76x 105x   105x 591x 583x 505x   78x     105x      
export enum IntegerSize {
	Eight = 8,
	Sixteen = 16
}
 
export interface CommandValue {
	size: IntegerSize;
	value: number;
}
 
/**
	This class lets us encode byte sequences in an easy to use manner and then view multiple different representations of them later (i.e. as usigned 8bit integers, hex strings, as byte-words etc.)
*/
export class CommandEncoder {
 
	values: CommandValue[] = [];
	hasHeader: boolean = false;
 
	constructor() {
		this.values.length = 4 // Minimum length is the length of the header
	}
	/**
		Request headers all follow a known format
		1. sid
		2. cid
		3. sequence byte ( for associating request to response, will be set before command is sent )
		4. length byte ( of data payload, will also be automatically filled when the command is serialized )
	*/
	setHeader = (sid: number, cid: number) => {
		this.hasHeader = true;
 
		this.values[0] = { 
			size: IntegerSize.Eight,
			value: sid
		};
 
		this.values[1] = {
			size: IntegerSize.Eight,
			value: cid
		};
 
		// this will eventually be sequence id
		this.values[2] = {
			size: IntegerSize.Eight,
			value: 0x00
		};
 
		// this will eventually be length
		this.values[3] = {
			size: IntegerSize.Eight,
			value: 0x00
		};
	}
 
	/// Encode a UInt8
	addUInt8 = (value: number) => {
		this.values.push({
			size: IntegerSize.Eight,
			value: value
		});
	}
 
	/// Encode a UInt16
	addUInt16 = (value: number) => {
		this.values.push({
			size: IntegerSize.Sixteen,
			value
		});
	}
 
	addASCIIArray = (value: string) => {
		for (var i = 0; i < value.length; i++) {
			var charcode = value.charCodeAt(i);
			this.addUInt8(charcode);
		}
	}
 
	/// Update the length byte to match the payload size
	updateLength = () => {
		this.values[3] = {
			size: IntegerSize.Eight,
			value: this.byteCount() - 4 // minus the header length
		}
	}
 
	/// Set the sequence number of this command
	setSequence = (seq: number) => {
		this.values[2] = {
			size: IntegerSize.Eight,
			value: seq
		}
	}
	/// Return the sequence number of this command
	getSequence = (): number => {
		return this.values[2].value;
	}
 
	/// Returns the payload byte size
	byteCount = (): number => {
		let i = 0;
 
		for ( let value of this.values ) {
			if ( value === undefined ) { continue; }
			if ( value.size === IntegerSize.Eight ) {
				i = i + 1;
			} else {
				i = i + 2;
			}
		}
		return i;
	}
}