///|
/// Reads a 0, 1, 2 or 4 byte little-endian short item as an unsigned value.
/// Int64 preserves the entire 32-bit unsigned domain on every backend.
pub fn unsigned_value(data : Bytes) -> Result[Int64, Diagnostic] {
  let size = data.length()
  if size != 0 && size != 1 && size != 2 && size != 4 {
    return Err(
      diagnostic(0, "value_size", "Short value must contain 0, 1, 2 or 4 bytes"),
    )
  }
  let mut value : Int64 = 0
  for i = 0; i < size; i = i + 1 {
    value = value | (data[i].to_int().to_int64() << (i * 8))
  }
  Ok(value)
}

///|
/// Reads a short item as a two's-complement signed value.
pub fn signed_value(data : Bytes) -> Result[Int64, Diagnostic] {
  match unsigned_value(data) {
    Err(error) => Err(error)
    Ok(value) => {
      let bits = data.length() * 8
      if bits > 0 && (value & (1L << (bits - 1))) != 0 {
        Ok(value - (1L << bits))
      } else {
        Ok(value)
      }
    }
  }
}

///|
fn item_unsigned(item : Item) -> Int64 {
  match unsigned_value(item.data) {
    Ok(value) => value
    Err(_) => 0 // Only used with short items returned by parse_items.
  }
}

///|
fn item_signed(item : Item) -> Int64 {
  match signed_value(item.data) {
    Ok(value) => value
    Err(_) => 0
  }
}