///|
/// 字节序比较:逐字节比,前缀相同时短的小。
/// 必须自己写 —— 不能依赖 String 的字典序,因为 key 是二进制。
///
/// **返回值恒为 -1 / 0 / 1**,不返回长度差值。
/// 这样调用方可以安全地写 `== -1` 判断,而不只是依赖符号。
pub fn compare_bytes(a : Bytes, b : Bytes) -> Int32 {
  let n = if a.length() < b.length() { a.length() } else { b.length() }
  for i in 0.. y {
      return 1
    }
  }
  if a.length() < b.length() {
    -1
  } else if a.length() > b.length() {
    1
  } else {
    0
  }
}

///|
/// 字符串 key 的字节序比较。
///
/// 存在的意义:把 UTF-8 编码细节收在库内,调用方(dbcli / 测试)不用自己
/// 处理 Bytes 转换,也不会误用 `String::compare`(它按长度优先,不是字节序)。
pub fn compare_strings(a : String, b : String) -> Int32 {
  compare_bytes(@utf8.encode(a), @utf8.encode(b))
}

///|
/// 内存写缓冲。当前用「有序数组 + 二分」,够跑通全部正确性测试。
/// Week 3 若性能不够,再换成跳表(接口不变)。
pub struct MemTable {
  entries : Array[Entry]
  mut bytes : Int32
  limit : Int32
}

///|
pub fn MemTable::new(limit : Int32) -> MemTable {
  { entries: [], bytes: 0, limit, }
}

///|
/// 第一个 >= key 的位置。
fn MemTable::lower_bound(self : MemTable, key : Key) -> Int32 {
  let mut lo = 0
  let mut hi = self.entries.length()
  while lo < hi {
    let mid = (lo + hi) / 2
    if compare_bytes(self.entries[mid].key, key) < 0 {
      lo = mid + 1
    } else {
      hi = mid
    }
  }
  lo
}

///|
/// 插入一条已构造好的条目(可能是墓碑)。
/// WAL 重放走这条路径:`mt.insert(rec.to_entry())`。
///
/// 同一个 key 后写的覆盖先写的。**这里不做 seq 比较** ——
/// 调用方必须保证按 seq 升序插入(WAL 是追加写,天然有序)。
pub fn MemTable::insert(self : MemTable, entry : Entry) -> Unit {
  let idx = self.lower_bound(entry.key)
  if idx < self.entries.length() &&
    compare_bytes(self.entries[idx].key, entry.key) == 0 {
    let old = self.entries[idx]
    // 覆盖写只调整 value 部分的字节数:key 长度不变。
    self.bytes = self.bytes + entry.value.length() - old.value.length()
    self.entries[idx] = entry
  } else {
    self.entries.insert(idx, entry)
    // +16 是 seq(8) + deleted 标记 + 数组槽位的估算开销,
    // 只用于触发 flush 阈值,不要求精确。
    self.bytes = self.bytes + entry.key.length() + entry.value.length() + 16
  }
}

///|
/// 写入的便捷形式。走 `Op::Put` 而不是直接构造 Entry:
/// 所有写入都经过「外部意图 → 内部条目」这一层转换,
/// 墓碑语义只在 `Op::to_entry` 一处定义,不会出现两个地方各写一套。
pub fn MemTable::put(
  self : MemTable,
  key : Key,
  value : Value,
  seq : UInt64,
) -> Unit {
  self.insert(Op::Put(key, value).to_entry(seq))
}

///|
/// 删除的便捷形式。写一条墓碑,不真的移除条目 ——
/// 真的移除会让更底层的旧值「复活」。
pub fn MemTable::delete(self : MemTable, key : Key, seq : UInt64) -> Unit {
  self.insert(Op::Delete(key).to_entry(seq))
}

///|
/// 重放一条 WAL 记录。恢复路径的唯一入口。
pub fn MemTable::apply(self : MemTable, rec : WalRecord) -> Unit {
  self.insert(rec.to_entry())
}

///|
/// 读。返回 None 表示这个 memtable 里没有(不代表全局没有)。
pub fn MemTable::get(self : MemTable, key : Key) -> Entry? {
  let idx = self.lower_bound(key)
  if idx < self.entries.length() &&
    compare_bytes(self.entries[idx].key, key) == 0 {
    Some(self.entries[idx])
  } else {
    None
  }
}

///|
/// 是否该刷盘了。
pub fn MemTable::is_full(self : MemTable) -> Bool {
  self.bytes >= self.limit
}

///|
/// 按 key 升序导出,供刷盘和归并迭代使用。
pub fn MemTable::to_entries(self : MemTable) -> Array[Entry] {
  self.entries
}

///|
/// 清空。**只在 flush 成功后调用** ——
/// 先落盘、再清空,顺序反了就是丢数据。
pub fn MemTable::clear(self : MemTable) -> Unit {
  self.entries.clear()
  self.bytes = 0
}