JoshGlazebrook / smart-buffer

smart-buffer is a Buffer wrapper that adds automatic read & write offset tracking, string operations, data insertions, and more.
https://www.npmjs.com/package/smart-buffer
MIT License
101 stars 17 forks source link

VarInt support #45

Open soanvig opened 2 years ago

soanvig commented 2 years ago

Hey! One thing I'm missing is VarInt support. I currently implemented support for this as follows using varint library. It does not comply to current code standards, and I had no time to adapt to them - that's why I wrote this dirty implementation and no PR.

Also, your readOffset is private (not protected) so I cannot easily extend, thus as any cast in read function.

WDYT about adding support for that style of integers into SmartBuffer?

export class SmartBuffer extends OriginalSmartBuffer {

  /** @TODO add tests */
  public writeVarInt (int: number): SmartBuffer {
    const INT = Math.pow(2, 31);
    const MSB = 0x80;
    const REST = 0x7F;
    const MSBALL = ~REST;

    if (int > Number.MAX_SAFE_INTEGER) {
      throw new RangeError('Could not encode varint');
    }

    const out = [];
    let offset = 0;

    while (int >= INT) {
      out[offset++] = (int & 0xFF) | MSB;
      int /= 128;
    }
    while (int & MSBALL) {
      out[offset++] = (int & 0xFF) | MSB;
      int >>>= 7;
    }
    out[offset] = int | 0;

    this.writeBuffer(Buffer.from(out));

    return this;
  }

  /** @TODO add tests */
  public readVarInt (): number {
    const MSB = 0x80;
    const REST = 0x7F;

    let res = 0;
    let shift = 0;
    let counter = 0;
    let b;
    const buffer = (this as any)._buff;

    do {
      if (shift > 49) {
        throw new RangeError('Could not decode varint');
      }
      b = buffer[this.readOffset + counter];
      counter += 1;
      res += shift < 28
        ? (b & REST) << shift
        : (b & REST) * Math.pow(2, shift);
      shift += 7;
    } while (b >= MSB);

    this.readOffset += counter;

    return res;
  };
}
JoshGlazebrook commented 2 years ago

I don't see why not. Do you have time to make a PR?

soanvig commented 2 years ago

Yeah, I think I can do that. I've already battle-tested my implementation on Minecraft server protocol, and I'm positive it works correctly.

Will post soon

soanvig commented 2 years ago

@JoshGlazebrook probably done, not sure though https://github.com/JoshGlazebrook/smart-buffer/pull/47