// MoonDNS Binary Buffer for Serialization

///|
/// Dynamic byte buffer with big-endian integer support and in-place patching
pub(all) struct DnsBuffer {
  bytes : Array[Byte]
}

///|
pub fn DnsBuffer::new() -> DnsBuffer {
  { bytes: [] }
}

///|
pub fn DnsBuffer::length(self : DnsBuffer) -> Int {
  self.bytes.length()
}

///|
pub fn DnsBuffer::write_byte(self : DnsBuffer, b : Byte) -> Unit {
  self.bytes.push(b)
}

///|
pub fn DnsBuffer::write_uint16_be(self : DnsBuffer, val : UInt16) -> Unit {
  let v = val.to_int()
  self.bytes.push(((v >> 8) & 0xFF).to_byte())
  self.bytes.push((v & 0xFF).to_byte())
}

///|
pub fn DnsBuffer::write_uint_be(self : DnsBuffer, val : UInt) -> Unit {
  let b0 = ((val >> 24) & 0xFFU).reinterpret_as_int().to_byte()
  let b1 = ((val >> 16) & 0xFFU).reinterpret_as_int().to_byte()
  let b2 = ((val >> 8) & 0xFFU).reinterpret_as_int().to_byte()
  let b3 = (val & 0xFFU).reinterpret_as_int().to_byte()
  self.bytes.push(b0)
  self.bytes.push(b1)
  self.bytes.push(b2)
  self.bytes.push(b3)
}

///|
pub fn DnsBuffer::write_bytes(self : DnsBuffer, bs : Bytes) -> Unit {
  for b in bs {
    self.bytes.push(b)
  }
}

///|
pub fn DnsBuffer::write_fixedarray(
  self : DnsBuffer,
  arr : FixedArray[Byte],
) -> Unit {
  for b in arr {
    self.bytes.push(b)
  }
}

///|
pub fn DnsBuffer::set_uint16_be(self : DnsBuffer, pos : Int, val : Int) -> Unit {
  self.bytes[pos] = ((val >> 8) & 0xFF).to_byte()
  self.bytes[pos + 1] = (val & 0xFF).to_byte()
}

///|
pub fn DnsBuffer::to_bytes(self : DnsBuffer) -> Bytes {
  Bytes::from_array(self.bytes)
}