import { memory: Memory<{ initial: 1 }> } from 'env';
type StringIterator = {
  length: i32,
  index: i32,
  addr: i32,
  start: i32,
  value: i32,
  done: i32
};

let offset: i32 = 0;
function malloc(size: i32) : i32 {
  const pointer: i32 = __DATA_LENGTH__ + offset;
  offset += size;
  return pointer;
}

// Create string iterator object.
function getStringIterator(addr: i32) : StringIterator {
  const iterator: StringIterator = malloc(sizeof(StringIterator));
  let length: i32 = 0;
  let byte: i32 = 0;
  let shift: i32 = 0;

  // Decode varuint32 length header
  while (true) {
    byte = i32.load8_u(addr);
    length = length | ((byte & 0x7f) << shift);
    addr += 1;
    if ((byte & 0x80) == 0) {
      break;
    }
    shift += 7;
  }

  iterator = { done: false, length, index: 0, addr, start: addr };

  return iterator;
}

export function next(iterator: StringIterator): StringIterator {
  if (iterator.length == 0 || iterator.index == iterator.length) {
    iterator.done = true;
    iterator.value = 0;
    return iterator;
  }

  let value: i32 = 0;
  let shift: i32 = 0;
  let byte: i32 = 0;
  let addr: i32 = iterator.addr;

  while (true) {
    byte = i32.load8_u(addr);
    value = value | ((byte & 0x7f) << shift);
    addr += 1;
    if ((byte & 0x80) == 0) {
      break;
    }
    shift += 7;
  }

  iterator = {
    index: iterator.index + 1,
    addr,
    value
  };

  return iterator;
}

export function reset(iterator: StringIterator) {
  iterator = {
    addr: iterator.start,
    index: 0,
    done: 0,
    value: 0
  };
}

