leap-protocol/leap-js

View on GitHub
src/mapGenerator.js

Summary

Maintainability
B
5 hrs
Test Coverage
// Copyright © 2020 Hoani Bryson
// License: MIT (https://mit-license.org/)
//
// Map Generator
//
// Processes configuration into simple map lookups for fast encoding
//

const itemData = require('./itemData');
const explore = require('./explore');
const protocolKey = require('./protocolKey');

exports.generate_maps = function generate_maps(protocol_root) {
  const branches = explore.extract_branches(protocol_root, []);
  const addr_path = [];
  const roots = [];
  const encode_map = {};
  const decode_map = {};

  let addr = 0;
  let prev_depth = 0;
  let max_depth = -1;
  // gather the corresponding data structures for each branch
  for (let i in branches) {
    const branch = branches[i];
    roots.push(explore.get_struct(protocol_root, branch.split('/')));
  }

  // This loop populates the correct data for every possible address
  // defined in the protocol
  for (let i in roots) {
    const root = roots[i];
    const branch = branches[i];
    const depth = (branch.match(/\//) || []).length;

    // When we burrow to a new address nesting, ensure the address
    // tracking has an entry ready to be updated
    if (max_depth < depth) {
      addr_path.push("");
    }

    // Handle address generation.
    // If the branch defines no address it is incremented
    // If it does have an address, we use the nested addressing rules
    // See leap-protocol.github.io for more details
    if (protocolKey.ADDR in root) {
      if (depth == 0) {
        // The root depth sets address explicitly
        addr_path[depth] = root[protocolKey.ADDR];
      }
      else {
        // Nested address specifications add to specified addresses further up
        // the chain.
        const int_addr = to_addr_int(addr_path[depth-1]) +
          to_addr_int(root[protocolKey.ADDR]);
        addr_path[depth] = to_addr_string(int_addr);
      }
    }
    else {
      if (addr_path[0] == "") {
        // Default first entry
        addr_path[0] = "0000";
      }
      else {
        // When address is not specified, increment by one
        addr_path[depth] = to_addr_string(
          to_addr_int(addr_path[prev_depth]) + 1
        );
      }
    }

    // Configure address depths for the next branch
    prev_depth = depth;
    max_depth = Math.max(max_depth, depth);
    addr = addr_path[depth];


    // Extract a list of branches which come off the current address
    const data_branches = [];
    const ends = explore.extract_decendants(root, []);
    for (i in ends) {
      const end = ends[i];
      if (end != "") {
        data_branches.push(
          [branch, end].join('/')
        );
      }
      else {
        data_branches.push(branch);
      }
    }

    // Extract a set of types associated with all branches coming off the
    // current address
    const types = explore.extract_types(root, []);

    const item_data = new itemData.ItemData(branch, addr, data_branches, types);
    encode_map[branch] = item_data;
    decode_map[addr] = item_data;
  }
  return [encode_map, decode_map];
}



function to_addr_string(ivalue) {
  return ("0000" + ivalue.toString(16)).substr(-4);
}

function to_addr_int(svalue) {
  return parseInt(svalue, 16);
}