///|
/// Return the default UAX #14 break kind after the last grapheme returned by
/// next() or iter(). Before the first grapheme, including for empty input,
/// returns Prohibited. Exhaustion preserves the last kind (Mandatory for
/// nonempty text). Repeated queries do not advance the grapheme cursor.
///
/// Only complete grapheme ends are queried; default line break opportunities
/// inside a cluster are not exposed. This does not change UAX #29 segmentation
/// or recompute line breaking classes per cluster.
///
/// The first query after a grapheme prepares line breaking context for the
/// whole input in O(n) time and space. Subsequent queries scan that context
/// forward, taking O(n) total time over a complete traversal. Traversal without
/// this query does not initialize or run the line breaking algorithm.
///
/// ```mbt check
/// test {
///   let graphemes = @segmentation.graphemes("ab c")
///   let kinds = []
///   for grapheme in graphemes {
///     kinds.push((grapheme.to_owned(), graphemes.line_break()))
///   }
///   debug_inspect(
///     kinds,
///     content=(
///       #|[
///       #|  ("a", Prohibited),
///       #|  ("b", Prohibited),
///       #|  (" ", Allowed),
///       #|  ("c", Mandatory),
///       #|]
///     ),
///   )
/// }
/// ```
pub fn Graphemes::line_break(self : Graphemes) -> BreakOpportunity {
  if self.offset == 0 {
    return Prohibited
  }
  let breaks = if self.breaks is Some(breaks) {
    breaks
  } else {
    let breaks = line_breaks(self.text)
    self.breaks = Some(breaks)
    breaks
  }
  // The cursors share the same input, whose final boundary is Mandatory.
  // Consequently this scan always reaches or passes the current cluster end.
  while breaks.offset < self.offset {
    ignore(breaks.next())
  }
  if breaks.offset == self.offset {
    breaks.opportunity()
  } else {
    Prohibited
  }
}