///|
pub struct Encoder {
  generation_value : Generation
  source : Array[Symbols]
}

///|
pub fn Encoder::new(
  id : Int32,
  input : Symbols,
  width : Int32,
) -> Encoder raise CodeError {
  if width < 1 || width > 4096 {
    raise Limit("encoder width must be 1..4096")
  }
  if input.length() == 0 {
    raise Invalid("empty input has no generation")
  }
  let count = (input.length() + width - 1) / width
  let generation = Generation::new(id, count, width, input.length())
  let source : Array[Symbols] = []
  for i in 0.. Encoder raise CodeError {
  if source.length() != generation.count() {
    raise Shape("source symbol count mismatch")
  }
  let detached : Array[Symbols] = []
  for symbol in source {
    if symbol.length() != generation.width() {
      raise Shape("source symbol width mismatch")
    }
    detached.push(symbol)
  }
  let last_symbol = source[source.length() - 1]
  let used = generation.length() - (generation.count() - 1) * generation.width()
  for i in used.. Generation {
  self.generation_value
}

///|
pub fn Encoder::source_symbols(self : Encoder) -> Array[Symbols] {
  let out : Array[Symbols] = []
  for symbol in self.source {
    out.push(symbol)
  }
  out
}

///|
pub fn Encoder::systematic(
  self : Encoder,
  index : Int32,
  sequence : Int32,
) -> Packet raise CodeError {
  if index < 0 || index >= self.generation_value.count() {
    raise Invalid("source index out of range")
  }
  let values = Array::make(self.generation_value.count(), 0)
  values[index] = 1
  Packet::new(self.generation_value, sequence, {
    coefficients: { values, },
    payload: self.source[index],
  })
}

///|
pub fn Encoder::encode(
  self : Encoder,
  coefficients : Symbols,
  sequence : Int32,
) -> Packet raise CodeError {
  if coefficients.length() != self.generation_value.count() {
    raise Shape("encoder coefficient count mismatch")
  }
  if sequence < 0 {
    raise Invalid("negative packet sequence")
  }
  let values = Array::make(self.generation_value.width(), 0)
  for i in 0..