// MoonDNS - Pure MoonBit Authoritative DNS Server
// Copyright 2026 chgttyyr
// Licensed under the Apache-2.0 License.
///|
/// MoonDNS Release Version String
pub const VERSION : String = "0.1.0"
///|
/// Public facade to create a fully initialized DnsServer from a BIND master-file zone text
pub fn create_server_from_zone_text(
origin : String,
zone_text : String,
) -> Result[@transport.DnsServer, @types.DnsError] {
let zone = match @zone.parse_zone_text(origin, zone_text) {
Ok(z) => z
Err(e) => return Err(e)
}
Ok(@transport.DnsServer::new(zone))
}
///|
/// High-level helper to query an in-memory DnsServer directly and obtain answered records
pub fn quick_resolve(
server : @transport.DnsServer,
domain : String,
rtype : @types.RType,
) -> Result[Array[@types.Record], @types.DnsError] {
let query = @types.Message::new_query(0x1337, domain, rtype)
let raw_req = @codec.encode_message(query)
let raw_resp = match server.process_udp(raw_req) {
Ok(bytes) => bytes
Err(e) => return Err(e)
}
let resp_msg = match @codec.decode_message(raw_resp) {
Ok(msg) => msg
Err(e) => return Err(e)
}
Ok(resp_msg.answers)
}
///|
fn hex_nibble_to_char(n : Int) -> Char {
if n < 10 {
Int::unsafe_to_char(48 + n)
} else {
Int::unsafe_to_char(97 + n - 10)
}
}
///|
fn char_to_hex_nibble(c : Int) -> Int {
if c >= 48 && c <= 57 {
c - 48
} else if c >= 97 && c <= 102 {
c - 97 + 10
} else if c >= 65 && c <= 70 {
c - 65 + 10
} else {
0
}
}
///|
/// Helper to convert binary Bytes into a lowercase hexadecimal string
pub fn bytes_to_hex(bytes : Bytes) -> String {
let buf = StringBuilder()
for i = 0; i < bytes.length(); i = i + 1 {
let b = bytes[i].to_int() & 0xFF
let hi = (b >> 4) & 0x0F
let lo = b & 0x0F
buf.write_char(hex_nibble_to_char(hi))
buf.write_char(hex_nibble_to_char(lo))
}
buf.to_string()
}
///|
/// Helper to convert a hexadecimal string into binary Bytes
pub fn hex_to_bytes(hex : String) -> Bytes {
let len = hex.length()
let writer = @bytes_io.ByteWriter::new()
let mut i = 0
while i + 1 < len {
let h1 = char_to_hex_nibble(hex[i].to_int())
let h2 = char_to_hex_nibble(hex[i + 1].to_int())
let b = (h1 << 4) | h2
writer.write_byte(b.to_byte())
i = i + 2
}
writer.to_bytes()
}
///|
/// Direct raw DNS packet resolution over UDP pipeline
pub fn resolve_raw_packet(
server : @transport.DnsServer,
raw_req : Bytes,
) -> Result[Bytes, @types.DnsError] {
server.process_udp(raw_req)
}
///|
/// WebAssembly/JS-friendly hex packet resolution: takes hex string, returns response hex string
pub fn resolve_hex_packet(
server : @transport.DnsServer,
hex_req : String,
) -> Result[String, @types.DnsError] {
let req_bytes = hex_to_bytes(hex_req)
match server.process_udp(req_bytes) {
Ok(resp_bytes) => Ok(bytes_to_hex(resp_bytes))
Err(e) => Err(e)
}
}