1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! A library for interpreting & manipulating Finagle/linkerd [dtab]s.
//!
//! The goal of this library is to provide a DSL for constructing and
//! manipulating dtabs that uses Rust's type system to ensure that invalid
//! dtabs cannot be represented, rather than just representing them as strings.
//!
//! [dtab]: https://linkerd.io/in-depth/dtabs/
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate serde;
#[macro_use] extern crate serde_derive;
//
// #[macro_use] extern crate nom;

// extern crate regex;

use std::fmt;

pub mod nametree;
pub mod path;

pub use self::nametree::*;


/// Macro for constructing a [`Dentry`].
///
/// This allows us to make [`Dentry`]s somewhat more ergonomically
/// than using the `>>` operator (since it doesn't require
/// the use of grouping symbols for the destination side of the
/// Dentry when using the [`NameTree`] DSL).
///
/// The macro also allows the use of `=>` rather than `>>`, as to
/// more closely match the dtab synbtax.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate dtab;
/// # fn main() {
/// use dtab::NameTree;
///
/// let dentry = dentry!( "/iceCreamStore" =>
///     NameTree::from("/smitten") | "/humphrys" | "/birite" | "/three-twins" );
///
/// assert_eq!(
///   "/iceCreamStore => /smitten | /humphrys | /birite | /three-twins;"
/// , &dentry.to_string()
/// );
/// # }
/// ```
///
#[macro_export]
macro_rules! dentry {
  ($src: expr => $dst: expr ) => ($crate::Dentry {
      prefix: $crate::NameTree::from($src), dst: $dst
  })
}

/// Convenience macro for making [`Dtab`]s.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate dtab;
/// # fn main() {
/// use dtab::NameTree;
///
/// let dtab = dtab![
///   "/smitten"       => NameTree::from("/USA/CA/SF/Harrison/2790");
///   "/iceCreamStore" => NameTree::from("/humphrys") | "/smitten";
/// ];
///
///
/// assert_eq!( &format!("{}", dtab)
///           , "/smitten => /USA/CA/SF/Harrison/2790;\n\
///              /iceCreamStore => /humphrys | /smitten;\n"
///           );
/// # }
/// ```
///
/// [`Dtab`]: type.Dtab.html
#[macro_export]
macro_rules! dtab {
  ($($src: expr => $dst: expr ;)+) => (
    $crate::Dtab(vec![ $(dentry!($src => $dst)),+ ])
  )
}
/// A `dtab` (delegation table) comprises a sequence of delegation rules.
#[derive(Debug, Clone, Serialize)]
pub struct Dtab(pub Vec<Dentry>);

impl fmt::Display for Dtab {
    #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.iter()
            .fold( Ok(())
                 , |r, ref entry| r.and_then(|_| {
                        write!(f, "{}\n", entry)
                    }))

    }
}

#[derive(Debug, Clone, Serialize)]
pub struct Dentry {
    #[serde(serialize_with ="nametree::serialize")]
    pub prefix: NameTree<String>
  , #[serde(serialize_with ="nametree::serialize")]
    pub dst: NameTree<String>
}

impl fmt::Display for Dentry {
    #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {};", self.prefix, self.dst)
    }
}