docs/vendor/ruby/2.6.0/gems/http_parser.rb-0.8.0/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java
package http_parser;

import java.nio.ByteBuffer;

public class Util {
//  public static String toString(http_parser.lolevel.HTTPParser p) {
//    StringBuilder builder = new StringBuilder();
//    
//    // the stuff up to the break is ephermeral and only meaningful
//    // while the parser is parsing. In general, this method is 
//    // probably only useful during debugging.
//
//    builder.append("state :"); builder.append(p.state); builder.append("\n");
//    builder.append("header_state :"); builder.append(p.header_state); builder.append("\n");
//    builder.append("strict :"); builder.append(p.strict); builder.append("\n");
//    builder.append("index :"); builder.append(p.index); builder.append("\n");
//    builder.append("flags :"); builder.append(p.flags); builder.append("\n");
//    builder.append("nread :"); builder.append(p.nread); builder.append("\n");
//    builder.append("content_length :"); builder.append(p.content_length); builder.append("\n");
//
//
//    builder.append("type :"); builder.append(p.type); builder.append("\n");
//    builder.append("http_major :"); builder.append(p.http_major); builder.append("\n");
//    builder.append("http_minor :"); builder.append(p.http_minor); builder.append("\n");
//    builder.append("status_code :"); builder.append(p.status_code); builder.append("\n");
//    builder.append("method :"); builder.append(p.method); builder.append("\n");
//    builder.append("upgrade :"); builder.append(p.upgrade); builder.append("\n");
//
//    return builder.toString();
//
//  }

  public static String error (String mes, ByteBuffer b, int beginning) {
      // the error message should look like this:
      //
      // Bla expected something, but it's not there (mes)
      // GEt / HTTP 1_1
      // ............^.
      //
      // |----------------- 72 -------------------------|

      // This is ridiculously complicated and probably riddled with
      // off-by-one errors, should be moved into high level interface.
      // TODO.
      
      // also: need to keep track of the initial buffer position in
      // execute so that we don't screw up any `mark()` that may have
      // been set outside of our control to be nice.

      final int mes_width = 72;
      int p   = b.position();      // error position
      int end = b.limit();         // this is the end
      int m   = end - beginning;    // max mes length
      
      StringBuilder builder = new StringBuilder();
      int p_adj = p;

      byte [] orig = new byte[0];
      if (m <= mes_width) {
        orig = new byte[m];
        b.position(beginning);
        b.get(orig, 0, m);
        p_adj = p-beginning;
        
        
      } else {
        // we'll need to trim bit off the beginning and/or end
        orig = new byte[mes_width];
        // three possibilities:
        // a.) plenty of stuff around p
        // b.) plenty of stuff in front of p
        // c.) plenty of stuff behind p
        // CAN'T be not enough stuff aorund p in total, because 
        // m>meswidth (see if to this else)

        int before = p-beginning;
        int after  = end - p;
        if ( (before > mes_width/2) && (after > mes_width/2)) {
          // plenty of stuff in front of and behind error
          p_adj = mes_width/2;
          b.position(p - mes_width/2);
          b.get(orig, 0, mes_width);
        } else if  (before <= mes_width/2) {
          // take all of the begining.
          b.position(beginning);
          // and as much of the rest as possible
          
          b.get(orig, 0, mes_width);

        } else {
          // plenty of stuff before
          before = end-mes_width;
          b.position(before);
          p_adj = p - before;
          b.get(orig, 0, mes_width);
        }
      }

      builder.append(new String(orig));
      builder.append("\n");
      for (int i = 0; i!= p_adj; ++i) {
        builder.append(".");
      }
      builder.append("^");


      b.position(p); // restore position
      return builder.toString();

  }
}
