code: private TrieNode buildTrie(BinaryComparable[] splits, int lower,
        int upper, byte[] prefix, int maxDepth) {
      final int depth = prefix.length;
      if (depth >= maxDepth || lower == upper) {
        return new LeafTrieNode(depth, splits, lower, upper);
      }
      InnerTrieNode result = new InnerTrieNode(depth);
      byte[] trial = Arrays.copyOf(prefix, prefix.length + 1);
      // append an extra byte on to the prefix
      int currentBound = lower;
      for(int ch = 0; ch < 255; ++ch) {
        trial[depth] = (byte) (ch + 1);
        lower = currentBound;
        while (currentBound < upper) {
          if (splits[currentBound].compareTo(trial, 0, trial.length) >= 0) {
            break;
          }
          currentBound += 1;
        }
        trial[depth] = (byte) ch;
        result.child[0xFF & ch] = buildTrie(splits, lower, currentBound, trial,
                                     maxDepth);
      }
      // pick up the rest
      trial[depth] = 127;
      result.child[255] = buildTrie(splits, currentBound, upper, trial,
                                    maxDepth);
      return result;
    }
docs: Given a sorted set of cut points, build a trie that will find the correct
  partition quickly.
  @param splits the list of cut points
  @param lower the lower bound of partitions 0..numPartitions-1
  @param upper the upper bound of partitions 0..numPartitions-1
  @param prefix the prefix that we have already checked against
  @param maxDepth the maximum depth we will build a trie for
  @return the trie node that will divide the splits correctly