///|
fn is_domain_rdata_field(record_type : String, index : Int) -> Bool {
match record_type {
"NS" | "CNAME" | "PTR" => index == 0
"MX" => index == 1
"SOA" => index == 0 || index == 1
"SRV" => index == 3
_ => false
}
}
///|
fn canonical_rdata_field(record : ResourceRecord, index : Int) -> String {
if is_domain_rdata_field(record.record_type, index) {
absolute_name(record.rdata[index], record.origin)
} else if record.record_type == "AAAA" {
lower(record.rdata[index])
} else {
record.rdata[index]
}
}
///|
fn write_canonical_rdata(out : StringBuilder, record : ResourceRecord) -> Unit {
for index in 0.. 0 {
out.write_char(' ')
}
out.write_string(canonical_rdata_field(record, index))
}
}
///|
/// Render one record with explicit owner, TTL, class, and type.
/// RDATA names are expanded against the `$ORIGIN` active at that record.
pub fn canonical_record_line(record : ResourceRecord) -> String {
let out = StringBuilder()
out.write_string(record.owner)
out.write_char(' ')
out.write_string(record.ttl.to_string())
out.write_char(' ')
out.write_string(record.class_name)
out.write_char(' ')
out.write_string(record.record_type)
out.write_char(' ')
write_canonical_rdata(out, record)
out.to_string()
}
///|
/// Produce stable, explicit master-file text in source record order.
pub fn render_canonical_zone(zone : Zone) -> String {
let out = StringBuilder()
out.write_string("$ORIGIN \{zone.origin}\n")
for record in zone.records {
out.write_string(canonical_record_line(record))
out.write_char('\n')
}
out.to_string()
}