///|
pub fn Feature::to_zero_based_start(self : Feature) -> Int {
  self.start - 1
}

///|
pub fn Feature::to_half_open_end(self : Feature) -> Int {
  self.end
}

///|
pub fn Feature::span(self : Feature) -> Span {
  { seqid: self.seqid, start: self.start, end: self.end }
}

///|
pub fn Span::length(self : Span) -> Int {
  self.end - self.start + 1
}

///|
pub fn Span::contains(self : Span, position~ : Int) -> Bool {
  self.start <= position && position <= self.end
}

///|
pub fn Span::overlaps(self : Span, other : Span) -> Bool {
  self.seqid == other.seqid &&
  self.start <= other.end &&
  self.end >= other.start
}

///|
pub fn Span::overlap_length(self : Span, other : Span) -> Int {
  if !self.overlaps(other) {
    0
  } else {
    let start = if self.start > other.start { self.start } else { other.start }
    let end = if self.end < other.end { self.end } else { other.end }
    end - start + 1
  }
}

///|
pub fn Span::to_bed_start(self : Span) -> Int {
  self.start - 1
}

///|
pub fn Span::to_bed_end(self : Span) -> Int {
  self.end
}

///|
pub fn Span::shift(self : Span, offset : Int) -> Span {
  { seqid: self.seqid, start: self.start + offset, end: self.end + offset }
}

///|
pub fn Span::expand(self : Span, bases : Int) -> Span {
  let start = if self.start - bases < 1 { 1 } else { self.start - bases }
  { seqid: self.seqid, start, end: self.end + bases }
}

///|
pub fn Span::distance_to(self : Span, other : Span) -> Int? {
  if self.seqid != other.seqid {
    None
  } else if self.overlaps(other) {
    Some(0)
  } else if self.end < other.start {
    Some(other.start - self.end)
  } else {
    Some(self.start - other.end)
  }
}

///|
pub fn Span::to_region_string(self : Span) -> String {
  "\{self.seqid}:\{self.start}-\{self.end}"
}

///|
pub fn Feature::region_string(self : Feature) -> String {
  self.span().to_region_string()
}