// Private byte helpers used by all value types

///|
fn read_float(b : Bytes, off : Int32) -> Float {
  let bits = b[off].to_int() |
    (b[off + 1].to_int() << 8) |
    (b[off + 2].to_int() << 16) |
    (b[off + 3].to_int() << 24)
  Float::reinterpret_from_int(bits)
}

///|
fn read_int(b : Bytes, off : Int32) -> Int32 {
  b[off].to_int() |
  (b[off + 1].to_int() << 8) |
  (b[off + 2].to_int() << 16) |
  (b[off + 3].to_int() << 24)
}

// Vector2: 8 bytes (x, y as float)

///|
/// 2D vector type.
pub struct Vector2 {
  x : Float
  y : Float
} derive(Eq, Debug)

///|
pub extend Vector2 with Eq::{equal, not_equal}

///|
pub extend Vector2 with @debug.Debug::{to_repr}

///|
/// Create a new Vector2.
pub fn Vector2::new(x : Float, y : Float) -> Vector2 {
  { x, y, }
}

///|
/// Serialize Vector2 to bytes.
pub fn Vector2::to_bytes(v : Vector2) -> Bytes {
  let buf = Buffer(size_hint=8)
  buf.write_float_le(v.x)
  buf.write_float_le(v.y)
  buf.to_bytes()
}

///|
/// Deserialize Vector2 from bytes.
pub fn Vector2::from_bytes(b : Bytes) -> Vector2 {
  { x: read_float(b, 0), y: read_float(b, 4), }
}

// Vector3: 12 bytes (x, y, z as float)

///|
/// 3D vector type.
pub struct Vector3 {
  x : Float
  y : Float
  z : Float
} derive(Eq, Debug)

///|
pub extend Vector3 with Eq::{equal, not_equal}

///|
pub extend Vector3 with @debug.Debug::{to_repr}

///|
/// Create a new Vector3.
pub fn Vector3::new(x : Float, y : Float, z : Float) -> Vector3 {
  { x, y, z, }
}

///|
/// Serialize Vector3 to bytes.
pub fn Vector3::to_bytes(v : Vector3) -> Bytes {
  let buf = Buffer(size_hint=12)
  buf.write_float_le(v.x)
  buf.write_float_le(v.y)
  buf.write_float_le(v.z)
  buf.to_bytes()
}

///|
/// Deserialize Vector3 from bytes.
pub fn Vector3::from_bytes(b : Bytes) -> Vector3 {
  { x: read_float(b, 0), y: read_float(b, 4), z: read_float(b, 8), }
}

// Vector4: 16 bytes (x, y, z, w as float)

///|
/// 4D vector type (also used as Quaternion).
pub struct Vector4 {
  x : Float
  y : Float
  z : Float
  w : Float
} derive(Eq, Debug)

///|
pub extend Vector4 with Eq::{equal, not_equal}

///|
pub extend Vector4 with @debug.Debug::{to_repr}

///|
/// Create a new Vector4.
pub fn Vector4::new(x : Float, y : Float, z : Float, w : Float) -> Vector4 {
  { x, y, z, w, }
}

///|
/// Serialize Vector4 to bytes.
pub fn Vector4::to_bytes(v : Vector4) -> Bytes {
  let buf = Buffer(size_hint=16)
  buf.write_float_le(v.x)
  buf.write_float_le(v.y)
  buf.write_float_le(v.z)
  buf.write_float_le(v.w)
  buf.to_bytes()
}

///|
/// Deserialize Vector4 from bytes.
pub fn Vector4::from_bytes(b : Bytes) -> Vector4 {
  {
    x: read_float(b, 0),
    y: read_float(b, 4),
    z: read_float(b, 8),
    w: read_float(b, 12),
  }
}