Skip to content

Introduction to Profiles

Ioannis Charalampidis edited this page Jun 17, 2016 · 2 revisions

JBB Profiles provide the required instructions for encoding and decoding user objects. Since each object in JBB is encoded as an array of properties, a profile provides the mapping between the property index and the property name. In addition, a profile might have additional initialisation information to cover more complicate object cases.

It's possible to use more than one profiles in a single JBB bundle so it's typical to have a separate profile for every class of objects you are using. For example, if you are using the three.js library you can use the jbb-profilethree` in addition to your projects profile. This way, it's the profile maintainer's responsibility to follow the library updates and not yours.

Profile Parts

A JBB Profile is composed of three parts, separated in different files:

  • profile-decoder.js provides the rules for decoding the objects.
  • profile-encoder.js provides the rules for encoding the objects.
  • profile-loader.js provides the rules for loading the objects into memory. (used by the compiler).

The first one is needed at run-time, while the latter two at compile-time.

Encoder

The profile-encoder consists of a single entry-point function and one getter function for every object. The encoder will call the main function for every instance and it should return an array with the object_id and the getter function.

The getter function should extract the relevant properties and return them as an array, as illustrated in the following example:

// The getter
function getter_MyObject( ) {
  return [
    inst.propA,
    inst.propB,
    inst.propC ];
}

// Entry point
module.exports = {
  ...
  encode: function( inst ) {
      if (inst instanceof MyObject) {
        return [0, getter_MyObject];
      } else if ( ... ) {
        ...
      }
  }
};

Decoder

The profile-decoder performs the inverse operation than the encoder. It consists of a similar entry point function that decodes for each object_id returns the appropriate factory object.

The factory object further consists of a create and init methods, which are used to create and initialise the object instance. This separation is needed because of the streaming nature of a JBB bundle. In some particular cases an object might be instantiated and others might refer to it, even though it's properties haven't arrived yet.

The following example illustrates a typical decoding module:

// The factory
var factory_MyObject = {
	props: 3,
	create: function() {
		return new MyObject();
	},
	init: function(inst, props, pagesize, offset) {
		inst.propA = props[offset+pagesize*0];
		inst.propB = props[offset+pagesize*1];
		inst.propC = props[offset+pagesize*2];
	}
}

// Entry point
module.exports = {
  ...
  decode: function( id ) {
    if (id == 0) {
      return factory_MyObject;
    }
  }
};

The offset and pagesize parameters are used to locate the correct property index when the properties are stored in a bulk array. For optimization purposes JBB is not slicing the array, rather you have to pick the correct index yourself. To do so, use the formula: offset+pagesize*<index>. For instance:

// First property
props[offset+pagesize*0];
// 10th property
props[offset+pagesize*9];

Loader

The profile-loader is used by the JBB compiler or the run-time source bundle loader to load the resources specified in the bundle.json. It consists of two functions:

  • The initialize function that is called once when the compiler loads the bundle.json specifications.
  • The load function that is called for every object in the specifications.

The load function should load/create the appropriate objects according to the specifications and trigger the callback function with an object containing the object(s) to put in the bundle. Usually you only need to create one object but there are cases were a loader creates a bulk of many other objects.

The following example illustrates a typical loading module:

// Entry point
module.exports = {

  // Called once when the compiler loads the bundle.json
  'initialize': function(cb, specs) {
  },
  
  // Called for every object class
  'load': function( loadClass, loadSpecs, name, callback ) {
    if (loadClass == "MyObject") {

      // Create an object that will contain
      // the loaded objects
      var objects = {};

      // Populate the objects using the name as a hint
      objects[name] = new MyObject( loadSpecs );

      // Callback 
      callback( null, objects );

    }
  }

};

Clone this wiki locally