impl Name {
/// Gets the underlying human-readable domain name
pub fn as_str(&self) -> &str { &self.0 }
+ /// Gets the number of labels in this name
+ pub fn labels(&self) -> u8 {
+ if self.as_str() == "." {
+ 0
+ } else {
+ self.as_str().chars().filter(|c| *c == '.').count() as u8
+ }
+ }
+ /// Gets a string containing the last `n` labels in this [`Name`] (which is also a valid name).
+ pub fn trailing_n_labels(&self, n: u8) -> Option<&str> {
+ let labels = self.labels();
+ if n > labels {
+ None
+ } else if n == labels {
+ Some(self.as_str())
+ } else if n == 0 {
+ Some(".")
+ } else {
+ self.as_str().splitn(labels as usize - n as usize + 1, ".").last()
+ }
+ }
}
impl core::ops::Deref for Name {
type Target = str;
records.sort_unstable();
for record in records.iter() {
- let periods = record.name().as_str().chars().filter(|c| *c == '.').count();
+ let record_labels = record.name().labels() as usize;
let labels = sig.labels.into();
- if periods != 1 && periods != labels {
- if periods < labels { return Err(ValidationError::Invalid); }
- let signed_name = record.name().as_str().splitn(periods - labels + 1, ".").last();
+ if record_labels != labels {
+ if record_labels < labels { return Err(ValidationError::Invalid); }
+ let signed_name = record.name().trailing_n_labels(sig.labels);
debug_assert!(signed_name.is_some());
if let Some(name) = signed_name {
signed_data.extend_from_slice(b"\x01*");