///|
/// Stable read view over one immutable Segment set.
///
/// Searchers keep the exact Segment array and tombstones captured by their
/// IndexReader generation. Later commits cannot mutate this view.
pub struct Searcher {
  segments : ReadOnlyArray[SnapshotSegment]
  statistics : SearchStatistics
}

///|
/// Creates a Searcher for one in-memory Segment.
pub fn Searcher::new(segment : Segment) -> Searcher {
  Searcher::from_segments(ReadOnlyArray::from_array([live_snapshot(segment)]))
}

///|
pub fn Searcher::from_segments(
  segments : ReadOnlyArray[SnapshotSegment],
) -> Searcher {
  { segments, statistics: SearchStatistics::from_segments(segments) }
}

///|
pub fn Searcher::segment_count(self : Searcher) -> Int {
  self.segments.length()
}

///|
/// Builds one Weight from snapshot-wide statistics, runs a Scorer against
/// every Segment, then performs one global Top-K selection.
pub fn Searcher::search(
  self : Searcher,
  query : &Query,
  collector : TopKCollector,
) -> ReadOnlyArray[SearchHit] {
  let weight = query.weight(self.statistics)
  let candidates : Array[SearchHit] = []
  for segment_ord in 0.. StoredDocument? {
  if address.segment_ord < 0 || address.segment_ord >= self.segments.length() {
    None
  } else {
    let snapshot = self.segments[address.segment_ord]
    if snapshot.is_deleted(address.doc_id) {
      None
    } else {
      snapshot.segment.doc(address.doc_id)
    }
  }
}