fb55 / bitfield Goto Github PK
View Code? Open in Web Editor NEWA bitfield implementation using buffers, compliant with the BitTorrent spec.
License: MIT License
A bitfield implementation using buffers, compliant with the BitTorrent spec.
License: MIT License
Version on npm seems to be missing the 'setAll' method, even though the version is '4.1.0', which should have that version. Downloaded and built from this repo, method makes it through the build, using that locally.
This could be handy because not always is the length the same as the buffer divised by 8
There should be some protection against spamming the RAM eg. by sending have
messages with large indexes. I'm not sure whether this module is the right place to handle this, maybe just adding a note to the readme will suffice.
Take a look at magnet-uri for an example of what this would look like.
I'm having issues getting this package to work. I've installed with "node install bitfield" and then created the sample program, directly from the readme:
import Bitfield from "bitfield";
const field = new Bitfield(256); // Create a bitfield with 256 bits.
field.set(128); // Set the 128th bit.
field.set(128, true); // Same as above.
field.get(128); // `true`
field.get(200); // `false` (all values are initialised to `false`)
field.get(1e3); // `false` (out-of-bounds is also false)
field.set(128, false); // Set the 128th bit to 0 again.
field.buffer; // The buffer used by the bitfield.
I created a package.json with {"type":"module"} in the working directory and executed, but I get this:
file:///home/myname/eclipse-workspace/myproject/buildTest.js:3
const field = new Bitfield(256); // Create a bitfield with 256 bits.
^
TypeError: Bitfield is not a constructor
at file:///home/myname/eclipse-workspace/myproject/buildTest.js:3:15
at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
at async Loader.import (internal/modules/esm/loader.js:166:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
I'm no node expert so it's entirely possible (probable?) that I'm doing something very obvious re: environment or what-have-you. Could someone give me an assist?
Iโd like to use this library to read a Transmission pieces bitfield, they provide a base64 encoded binary (pieces) and its pieces size (pieceSize), how would I go to use this library to read it?
I started using the module and it works fine but I have some issue while trying to use it with another language language (lua)
Programmers of the lua code asked me to export the bitfield (we need 128 values) as 4 integers and I have trouble doing this.
Seems like read from the buffer with readUInt32LE give unexpected results.
So I started investigating on this and notice there is a that trick : 128 >> (i % 8)
so creating a buffer of 128 bool and sending the index 0 to true give this :
var f = new bitfield(128)
f.set(0)
f.buffer
<Buffer 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>
if you only set(1)
<Buffer 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>
It makes sense if you read the code but I dont get the point of this trick and it s not easy to understand which bits are set if you looks at the buffer dump
I tried to find a way to export the data is the more easily undestable way but without success
for exemple lua programmers expect the output if I set the first bool to 1 only to be :
u32exports = [1,0,0,0]
Lines 35 to 62 in 0ba8d2d
@ line 50 this.buffer.length < length
should not be necessary since, line 38 already dose this check
I'm curious also when you grow the buffer, why don't you use set
?
e.g. like so:
BitField.prototype._grow = function (length) {
if (length <= this.grow) {
var newBuffer = new Container(length) // eslint-disable-line node/no-deprecated-api
if (newBuffer.fill) newBuffer.fill(0)
newBuffer.set(newBuffer)
this.buffer = newBuffer
}
}
Another thing: is Buffer really necessary? Can we not only use Uint8Array? A Buffer adds other overhead functionality that seems unnecessary. new Buffer(n)
is also deprecated and i don't think we need fill(0)
either if we just use Uint8Array...
Lines 1 to 3 in 0ba8d2d
BitField is shared between frontend or backend so can't we not just stick to using Uint8Array so we can expect the same thing in both environments.
Not having to worry about when buffer constructor is removed completely from Node and replaced with just an object
I also think _grow
can be factored out of the class to just be a helper function that returns a value or simply be put inlined since it is only used at one place
if (this.buffer.length < j + 1) {
// before:
// this._grow(Math.max(j + 1, Math.min(2 * this.buffer.length, this.grow)))
var buffer = new Uint8Array(Math.max(j + 1, Math.min(2 * this.buffer.length, this.grow)))
buffer.set(this.buffer)
this.buffer = buffer
}
function getByteSize (num) {
let out = num >> 3
if (num % 8 !== 0) out++
return out
}
class BitField {
constructor (data = 0, {grow} = {}) {
this.grow = (grow && isFinite(grow) && getByteSize(grow)) || 0
this.buffer = typeof data === 'number' ? new Uint8Array(getByteSize(data)) : data
}
get (i) {
const j = i >> 3
return (j < this.buffer.length) &&
!!(this.buffer[j] & (128 >> (i % 8)))
}
set (i, b = 1) {
const j = i >> 3
if (b) {
if (this.buffer.length < j + 1) {
const length = Math.max(j + 1, Math.min(2 * this.buffer.length, this.grow))
if (length <= this.grow) {
const newBuffer = new Uint8Array(length)
newBuffer.set(this.buffer)
this.buffer = newBuffer
}
}
// Set
this.buffer[j] |= 128 >> (i % 8)
} else if (j < this.buffer.length) {
// Clear
this.buffer[j] &= ~(128 >> (i % 8))
}
}
}
if (typeof module !== 'undefined') module.exports = BitField
WebTorrent loops over bitfields a bunch of time to check what is done and what not, So I figure this piece could be improved with a smarter forEach loop
get(i) {
const j = i >> 3
return (j < this.buffer.length) &&
!!(this.buffer[j] & (128 >> (i % 8)))
}
Solution:
forEach(fn, start = 0, end = this.buffer.length) {
for (
let i = start, j = i >> 3, x = i % 8, y = 128 >> x, buffer = this.buffer, byte = buffer[j];
i < end;
i++
) {
fn(!!(byte & (y >> x)), i)
y === 1
? (y = y << 7, x = 0, byte = buffer[++j])
: (y = y >> 1, x++)
}
}
forEach loop: 0.944091796875ms
for loop: 1.72314453125ms
fiddle: http://jsfiddle.net/nbr5u3jk/3/
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.