Skip to content

Instantly share code, notes, and snippets.

@LukasBombach
Last active June 24, 2019 21:02
export default class BinaryParser<T> {
private buffer: DataView;
private offset: number;
private varsInternal: Partial<T>;
constructor(buffer: DataView) {
this.buffer = buffer;
this.offset = 0;
this.varsInternal = {};
}
public vars(): Partial<T> {
return this.varsInternal;
}
public char(name: string) {
const value = this.buffer.getUint8(this.offset);
this.write(name, value);
this.offset += 1;
return this;
}
public short(name: string) {
const value = this.buffer.getUint16(this.offset, false);
this.write(name, value);
this.offset += 2;
return this;
}
public int(name: string) {
const value = this.buffer.getUint32(this.offset, true);
this.write(name, value);
this.offset += 4;
return this;
}
public sha(name: string) {
const value = this.buffer.getUint32(this.offset, true).toString(16);
const sanitizedValue = value === "0" ? "" : value;
this.write(name, sanitizedValue);
this.offset += 4;
return this;
}
private write(path: string, value: any) {
const keys = path.split(".");
const key = keys[keys.length - 1];
let node = this.varsInternal;
keys.slice(0, -1).forEach(function(k) {
if (node[k] === undefined) node[k] = {};
node = node[k];
});
node[key] = value;
}
}
import Converter from "../converter";
import Parser from "../parser";
type States = { [S in State]: number };
export interface ParseResult {
state: number;
substate: number;
}
export default class StateConverter {
private parse(data: DataView): ParseResult {
return new Parser<ParseResult>(data)
.char("state")
.char("substate")
.vars();
}
}
@LukasBombach
Copy link
Author

  private parse(data: DataView): ParseResult {
    return new Parser<ParseResult>(data)
      .char("state")
      .char("substate")
      .vars();
  }

Results in this error

Type 'Partial<ParseResult>' is not assignable to type 'ParseResult'.
Property 'state' is optional in type 'Partial<ParseResult>' but required in type 'ParseResult'.ts(2322)

@codemile
Copy link

Okay. I see what you're doing here.

Remove the generic type from the class.

export default class BinaryParser

Make the varInternals an any type.

 private varsInternal: any = {};

Now cast to the target type when calling the vars() method

  public vars<T>():T {
    return this.varsInternal as T;
  }

Since this is a parser. You can't assume you know the types, and the consumer of the type will make an assumption about the type when they get vars().

@aaronbeall
Copy link

aaronbeall commented Jun 24, 2019

I don't think the parser really benefits from the type argument. Even if you made the types work you could still use the class inconsistent with the type argument:

return new Parser<ParseResult>(data)
  .char("foo")
  .vars();

@LukasBombach
Copy link
Author

Ah, both of that is true. Thanks guys. Problem solved. How can we get that on StackOverflow?

@codemile
Copy link

This thread is more code review. Not really a SO answer.

@LukasBombach
Copy link
Author

Sure

@LukasBombach
Copy link
Author

Thanks though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment