Skip to content

Instantly share code, notes, and snippets.

@brianloveswords
Last active December 22, 2015 17:09
Show Gist options
  • Save brianloveswords/6504049 to your computer and use it in GitHub Desktop.
Save brianloveswords/6504049 to your computer and use it in GitHub Desktop.

Preface

So this was inspired both by @maxogden and @mcollina's talks at nodeconf.eu 2013. Max spoke about the power (and fun!) of understanding & manipulating with binary data in JavaScript, and Matteo pointed to a protocol called MQTT that manages to a flexible, featureful protocol with only a 2 byte overhead. In looking how they do that (http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html) I noticed they make rich use of the individual bits of those bytes. I realized that off the top of my head I didn't know how I would parse out that information and JavaScript, so I set up about to experimenting to see if I could figure it out without looking up the answer. After figuring it out I wrote a little mini monster protocol & tutorial to maybe help others understand this neat technique!

Now, Let's describe a whole monster in just one byte.

First we need to define the semantics of our bit field. As a reminder, a byte is made up of 8 bits, and each bit can be either a 1 or a 0. With well defined semantics up front, we can represent up to 8 units of information, one for each bit.

With our monster protocol, we will use up the first four bits represent the monster's size. We will interpret the four bits as one unsigned integer representing the height of the monster in stories. This means we can have a monster between 0 and 15 stories tall.

The last four bits represent what elements the monster can breath, 1 for "yes it can breath that element", 0 for "no it can't :("

So all together:

  • bits 1-4: size in stories
  • bit 5: fire
  • bit 6: lazer
  • bit 7: ice
  • bit 8: kittens

Say we want a lazer breathing 4 story monster. That would be represented with: 0100 0100

Now someone tells us we have following monster approaching: 1011 0111

What kind of monster is this? Can we create an object that describes this type of monster at a higher level?

When figuring out what attributes the monster has, we need some way of isolating just the parts we care about. For this we can use the bitwise AND operator (&).

The way bitwise AND works is by taking two sets of bits and returning a new set where the value of the bit for each position is 1 only when the value in that position in both sets is 1, otherwise it is 0. An example:

  0100
& 1100
------
  0100
// Since JS doesn't have a native notation for defining a set of bits,
// the best/most efficient way is to represent them with integers.
var SIZE_MASK = 15; // 0000 1111
var FIREBREATH = 16; // 0001 0000
var LAZERBREATH = 32; // 0010 0000
var ICEBREATH = 64; // 0100 0000
var KITTENBREATH = 128; // 1000 0000
var INCOMING = 183; // 1011 0111
var monster = {
sizeInStories: INCOMING & SIZE_MASK,
// 1011 0111
// & 0000 1111
// -----------
// 0000 0111 <-- (as an integer, 7 stories)
fireBreath: !!(INCOMING & FIREBREATH),
// 1011 0111
// & 0001 0000
// -----------
// 0001 0000 <-- (yes)
lazerBreath: !!(INCOMING & LAZERBREATH),
// 1011 0111
// & 0010 0000
// -----------
// 0010 0000 <-- (yes)
iceBreath: !!(INCOMING & ICEBREATH),
// 1011 0111
// & 0100 0000
// -----------
// 0000 0000 <-- (no)
kittenBreath: !!(INCOMING & KITTENBREATH),
// 1011 0111
// & 1000 0000
// -----------
// 1000 0000 <-- (yes)
};
// So we now have information about each of the 5 attributes:
// { sizeInStories: 7,
// fireBreath: true,
// lazerBreath: true,
// iceBreath: false,
// kittenBreath: true }
// And we transmitted all of that information in one byte of data!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment