///|
pub struct ZoneDocument {
record_values : Array[ZoneRecord]
origin_value : DomainName?
default_ttl_value : Ttl?
directive_count_value : Int
} derive(Eq, Debug)
///|
fn statement_is_directive(statement : ZoneStatement) -> Bool {
let tokens = statement.tokens()
tokens.length() > 0 &&
tokens[0].text().length() > 0 &&
tokens[0].text()[0].to_int() == 36
}
///|
/// Parse a complete caller-provided zone text into resolved records.
pub fn parse_zone(
text : String,
initial_origin? : DomainName? = None,
initial_ttl? : Ttl? = None,
max_tokens? : Int = 100000,
max_token_bytes? : Int = 65535,
) -> Result[ZoneDocument, ZoneError] {
match initial_origin {
Some(value) if !value.is_absolute() =>
return Err(
ZoneError::new(
RelativeNameWithoutOrigin,
"initial zone origin must be absolute",
SourceSpan::point(0, 0),
),
)
_ => ()
}
let statements = match lex_zone(text, max_tokens~, max_token_bytes~) {
Ok(value) => value
Err(error) => return Err(error)
}
let records : Array[ZoneRecord] = []
let mut origin = initial_origin
let mut default_ttl = initial_ttl
let mut previous_owner : DomainName? = None
let mut previous_ttl = initial_ttl
let mut directive_count = 0
for statement in statements {
if statement_is_directive(statement) {
let directive = match
parse_zone_directive(statement, current_origin=origin) {
Ok(value) => value
Err(error) => return Err(error)
}
directive_count = directive_count + 1
match directive {
OriginDirective(value) => {
origin = Some(value)
previous_owner = None
}
DefaultTtlDirective(value) => {
default_ttl = Some(value)
previous_ttl = Some(value)
}
}
} else {
let active_origin = match origin {
Some(value) => value
None => {
let token = statement.tokens()[0]
return Err(
ZoneError::new(
RelativeNameWithoutOrigin,
"zone record appears before an origin is established",
token.span(),
),
)
}
}
let inherited_ttl = match previous_ttl {
Some(value) => Some(value)
None => default_ttl
}
let record = match
parse_zone_record(
statement,
active_origin,
inherited_owner=previous_owner,
inherited_ttl~,
) {
Ok(value) => value
Err(error) => return Err(error)
}
previous_owner = Some(record.owner())
previous_ttl = Some(record.ttl())
records.push(record)
}
}
Ok({
record_values: records,
origin_value: origin,
default_ttl_value: default_ttl,
directive_count_value: directive_count,
})
}
///|
pub fn ZoneDocument::records(self : ZoneDocument) -> Array[ZoneRecord] {
self.record_values.copy()
}
///|
pub fn ZoneDocument::origin(self : ZoneDocument) -> DomainName? {
self.origin_value
}
///|
pub fn ZoneDocument::default_ttl(self : ZoneDocument) -> Ttl? {
self.default_ttl_value
}
///|
pub fn ZoneDocument::directive_count(self : ZoneDocument) -> Int {
self.directive_count_value
}