Skip to content

Instantly share code, notes, and snippets.

@baryon
Created January 31, 2024 06:16
Show Gist options
  • Save baryon/6a0f97fc55a39b826d6e3d40166afa59 to your computer and use it in GitHub Desktop.
Save baryon/6a0f97fc55a39b826d6e3d40166afa59 to your computer and use it in GitHub Desktop.
Convert between bigint and buffer
import { expect, use } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { buffer2bigint, bigint2buffer } from '../src/bigint'
use(chaiAsPromised)
describe('Test Utils', () => {
before(async () => {
})
it('test 0', async () => {
const value = 0
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test -1', async () => {
const value = -1
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test 1', async () => {
const value = 1
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint 0n', async () => {
const value = 0
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint -1n', async () => {
const value = -1n
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint 1n', async () => {
const value = 1n
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint 0x7f', async () => {
const value = 0x7f
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint 0x7f+1', async () => {
const value = 0x7f+1
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint 0x7f-1', async () => {
const value = 0x7f-1
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint -0x7f', async () => {
const value = -0x7f
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint 0xffffff', async () => {
const value = 0xffffff
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint -0xffffff', async () => {
const value = -0xffffff
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint max n', async () => {
const value = 1200n*10000n*10n**18n
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
it('test bigint neg n', async () => {
const value = -1200n*10000n*10n**18n
const buf = bigint2buffer(value)
console.log(buf.toString('hex'))
const result = buffer2bigint(buf)
console.log(result)
await expect(result).is.eq(BigInt(value))
})
})
// Converts a bigint into a sign-magnitude representation
export function bigint2buffer(value: number | bigint): Buffer {
let hex = value < 0 ? (-value).toString(16) : value.toString(16);
if (hex.length % 2 !== 0) hex = "0" + hex;
const m = parseInt("0x" + hex.slice(0, 2), 16);
if (m >= 0x7f) {
hex = "00" + hex;
}
let buffer = Buffer.from(hex, "hex");
if (value >= 0) {
return buffer;
}
for (let i = 0; i < buffer.length; i++) {
buffer[i] = ~buffer[i]!;
}
for (let i = buffer.length - 1; i >= 0; i--) {
if (buffer[i] === 0xff) {
buffer[i] = 0x00;
} else {
buffer[i]++;
break;
}
}
return buffer;
}
export function buffer2bigint(buffer: Buffer): bigint {
const isNegative = buffer[0]! & 0x80;
if (isNegative) {
let carry = true;
for (let i = buffer.length - 1; i >= 0; i--) {
buffer[i] = ~buffer[i]! & 0xff;
if (carry) {
carry = buffer[i] === 0xff;
buffer[i]++;
}
}
}
return (
BigInt("0x" + buffer.toString("hex")) *
(isNegative ? BigInt(-1) : BigInt(1))
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment