///|
/// Build from a strictly increasing database/index cursor without an exact Map.
/// Duplicate/order checks need O(1) state; sketch storage is O(config.width).
/// The cursor must read a consistent application snapshot throughout the scan.
pub fn Snapshot::from_sorted_ids(
  ids : Iter[UInt64],
  config : Config,
  scope~ : UInt64 = 0UL,
  epoch~ : UInt64 = 0UL,
  max_members~ : Int32 = 10000000,
) -> Snapshot raise ReconcileError {
  if max_members < 0 {
    raise InvalidConfig("negative streaming member limit")
  }
  let sketch = Sketch::new(config)
  let mut fingerprint = empty_fingerprint()
  let mut previous : UInt64? = None
  for id in ids {
    if fingerprint.count >= max_members {
      raise LimitExceeded("streaming snapshot members")
    }
    if previous is Some(last) && id <= last {
      raise InvalidConfig("streaming IDs must be strictly increasing")
    }
    sketch.insert(id)
    fingerprint = fingerprint_add(fingerprint, id, 1)
    previous = Some(id)
  }
  { scope, epoch, fingerprint, sketch, }
}