docs: private void parse(byte[] program) throws ScriptException {
          chunks = new ArrayList<>(5);   // Common size.
          ByteArrayInputStream bis = new ByteArrayInputStream(program);
          int initialSize = bis.available();
          while (bis.available() > 0) {
              int startLocationInProgram = initialSize - bis.available();
              int opcode = bis.read();
  
              long dataToRead = -1;
              if (opcode >= 0 && opcode < OP_PUSHDATA1) {
                  // Read some bytes of data, where how many is the opcode value itself.
                  dataToRead = opcode;
              } else if (opcode == OP_PUSHDATA1) {
                  if (bis.available() < 1) throw new ScriptException(ScriptError.SCRIPT_ERR_UNKNOWN_ERROR, "Unexpected end of script");
                  dataToRead = bis.read();
              } else if (opcode == OP_PUSHDATA2) {
                  // Read a short, then read that many bytes of data.
                  if (bis.available() < 2) throw new ScriptException(ScriptError.SCRIPT_ERR_UNKNOWN_ERROR, "Unexpected end of script");
                  dataToRead = Utils.readUint16FromStream(bis);
              } else if (opcode == OP_PUSHDATA4) {
                  // Read a uint32, then read that many bytes of data.
                  // Though this is allowed, because its value cannot be > 520, it should never actually be used
                  if (bis.available() < 4) throw new ScriptException(ScriptError.SCRIPT_ERR_UNKNOWN_ERROR, "Unexpected end of script");
                  dataToRead = Utils.readUint32FromStream(bis);
              }
  
              ScriptChunk chunk;
              if (dataToRead == -1) {
                  chunk = new ScriptChunk(opcode, null, startLocationInProgram);
              } else {
                  if (dataToRead > bis.available())
                      throw new ScriptException(ScriptError.SCRIPT_ERR_BAD_OPCODE, "Push of data element that is larger than remaining data");
                  byte[] data = new byte[(int)dataToRead];
                  checkState(dataToRead == 0 || bis.read(data, 0, (int)dataToRead) == dataToRead);
                  chunk = new ScriptChunk(opcode, data, startLocationInProgram);
              }
              // Save some memory by eliminating redundant copies of the same chunk objects.
              for (ScriptChunk c : STANDARD_TRANSACTION_SCRIPT_CHUNKS) {
                  if (c.equals(chunk)) chunk = c;
              }
              chunks.add(chunk);
          }
      }