123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- use core::str::FromStr;
- use core::result;
- use wire::{EthernetAddress, IpAddress, Ipv4Address, Ipv4Cidr, IpCidr};
- type Result<T> = result::Result<T, ()>;
- struct Parser<'a> {
- data: &'a [u8],
- pos: usize
- }
- impl<'a> Parser<'a> {
- fn new(data: &'a str) -> Parser<'a> {
- Parser {
- data: data.as_bytes(),
- pos: 0
- }
- }
- fn advance(&mut self) -> Result<u8> {
- match self.data.get(self.pos) {
- Some(&chr) => {
- self.pos += 1;
- Ok(chr)
- }
- None => Err(())
- }
- }
- fn try<F, T>(&mut self, f: F) -> Option<T>
- where F: FnOnce(&mut Parser<'a>) -> Result<T> {
- let pos = self.pos;
- match f(self) {
- Ok(res) => Some(res),
- Err(()) => {
- self.pos = pos;
- None
- }
- }
- }
- fn accept_eof(&mut self) -> Result<()> {
- if self.data.len() == self.pos {
- Ok(())
- } else {
- Err(())
- }
- }
- fn until_eof<F, T>(&mut self, f: F) -> Result<T>
- where F: FnOnce(&mut Parser<'a>) -> Result<T> {
- let res = f(self)?;
- self.accept_eof()?;
- Ok(res)
- }
- fn accept_char(&mut self, chr: u8) -> Result<()> {
- if self.advance()? == chr {
- Ok(())
- } else {
- Err(())
- }
- }
- fn accept_digit(&mut self, hex: bool) -> Result<u8> {
- let digit = self.advance()?;
- if digit >= b'0' && digit <= b'9' {
- Ok(digit - b'0')
- } else if hex && digit >= b'a' && digit <= b'f' {
- Ok(digit - b'a' + 10)
- } else if hex && digit >= b'A' && digit <= b'F' {
- Ok(digit - b'A' + 10)
- } else {
- Err(())
- }
- }
- fn accept_number(&mut self, max_digits: usize, max_value: u32,
- hex: bool) -> Result<u32> {
- let mut value = self.accept_digit(hex)? as u32;
- for _ in 1..max_digits {
- match self.try(|p| p.accept_digit(hex)) {
- Some(digit) => {
- value *= if hex { 16 } else { 10 };
- value += digit as u32;
- }
- None => break
- }
- }
- if value < max_value {
- Ok(value)
- } else {
- Err(())
- }
- }
- fn accept_mac_joined_with(&mut self, separator: u8) -> Result<EthernetAddress> {
- let mut octets = [0u8; 6];
- for n in 0..6 {
- octets[n] = self.accept_number(2, 0x100, true)? as u8;
- if n != 5 {
- self.accept_char(separator)?;
- }
- }
- Ok(EthernetAddress(octets))
- }
- fn accept_mac(&mut self) -> Result<EthernetAddress> {
- if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b'-')) {
- return Ok(mac)
- }
- if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b':')) {
- return Ok(mac)
- }
- Err(())
- }
- fn accept_ipv4(&mut self) -> Result<Ipv4Address> {
- let mut octets = [0u8; 4];
- for n in 0..4 {
- octets[n] = self.accept_number(3, 0x100, false)? as u8;
- if n != 3 {
- self.accept_char(b'.')?;
- }
- }
- Ok(Ipv4Address(octets))
- }
- fn accept_ip(&mut self) -> Result<IpAddress> {
- if let Some(()) = self.try(|p| p.accept_eof()) {
- return Ok(IpAddress::Unspecified)
- }
- if let Some(ipv4) = self.try(|p| p.accept_ipv4()) {
- return Ok(IpAddress::Ipv4(ipv4))
- }
- Err(())
- }
- }
- impl FromStr for EthernetAddress {
- type Err = ();
- /// Parse a string representation of an Ethernet address.
- fn from_str(s: &str) -> Result<EthernetAddress> {
- Parser::new(s).until_eof(|p| p.accept_mac())
- }
- }
- impl FromStr for Ipv4Address {
- type Err = ();
- /// Parse a string representation of an IPv4 address.
- fn from_str(s: &str) -> Result<Ipv4Address> {
- Parser::new(s).until_eof(|p| p.accept_ipv4())
- }
- }
- impl FromStr for IpAddress {
- type Err = ();
- /// Parse a string representation of an IPv4 address.
- fn from_str(s: &str) -> Result<IpAddress> {
- Parser::new(s).until_eof(|p| p.accept_ip())
- }
- }
- impl FromStr for Ipv4Cidr {
- type Err = ();
- /// Parse a string representation of an IPv4 CIDR.
- fn from_str(s: &str) -> Result<Ipv4Cidr> {
- Parser::new(s).until_eof(|p| {
- let ip = p.accept_ipv4()?;
- p.accept_char(b'/')?;
- let prefix_len = p.accept_number(2, 33, false)? as u8;
- Ok(Ipv4Cidr::new(ip, prefix_len))
- })
- }
- }
- impl FromStr for IpCidr {
- type Err = ();
- /// Parse a string representation of an IP CIDR.
- fn from_str(s: &str) -> Result<IpCidr> {
- Ipv4Cidr::from_str(s).map(IpCidr::Ipv4)
- }
- }
- #[cfg(test)]
- mod test {
- use super::*;
- #[test]
- fn test_mac() {
- assert_eq!(EthernetAddress::from_str(""), Err(()));
- assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"),
- Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00])));
- assert_eq!(EthernetAddress::from_str("01:23:45:67:89:ab"),
- Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab])));
- assert_eq!(EthernetAddress::from_str("cd:ef:10:00:00:00"),
- Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00])));
- assert_eq!(EthernetAddress::from_str("00:00:00:ab:cd:ef"),
- Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
- assert_eq!(EthernetAddress::from_str("00-00-00-ab-cd-ef"),
- Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
- assert_eq!(EthernetAddress::from_str("AB-CD-EF-00-00-00"),
- Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00])));
- assert_eq!(EthernetAddress::from_str("100:00:00:00:00:00"), Err(()));
- assert_eq!(EthernetAddress::from_str("002:00:00:00:00:00"), Err(()));
- assert_eq!(EthernetAddress::from_str("02:00:00:00:00:000"), Err(()));
- assert_eq!(EthernetAddress::from_str("02:00:00:00:00:0x"), Err(()));
- }
- #[test]
- fn test_ipv4() {
- assert_eq!(Ipv4Address::from_str(""), Err(()));
- assert_eq!(Ipv4Address::from_str("1.2.3.4"),
- Ok(Ipv4Address([1, 2, 3, 4])));
- assert_eq!(Ipv4Address::from_str("001.2.3.4"),
- Ok(Ipv4Address([1, 2, 3, 4])));
- assert_eq!(Ipv4Address::from_str("0001.2.3.4"), Err(()));
- assert_eq!(Ipv4Address::from_str("999.2.3.4"), Err(()));
- assert_eq!(Ipv4Address::from_str("1.2.3.4.5"), Err(()));
- assert_eq!(Ipv4Address::from_str("1.2.3"), Err(()));
- assert_eq!(Ipv4Address::from_str("1.2.3."), Err(()));
- assert_eq!(Ipv4Address::from_str("1.2.3.4."), Err(()));
- }
- #[test]
- fn test_ip() {
- assert_eq!(IpAddress::from_str(""),
- Ok(IpAddress::Unspecified));
- assert_eq!(IpAddress::from_str("1.2.3.4"),
- Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4]))));
- assert_eq!(IpAddress::from_str("x"), Err(()));
- }
- #[test]
- fn test_cidr() {
- let tests = [
- ("127.0.0.1/8",
- Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8))),
- ("192.168.1.1/24",
- Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8))),
- ("8.8.8.8/32",
- Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8))),
- ("8.8.8.8/0",
- Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8))),
- ("", Err(())),
- ("1", Err(())),
- ("127.0.0.1", Err(())),
- ("127.0.0.1/", Err(())),
- ("127.0.0.1/33", Err(())),
- ("127.0.0.1/111", Err(())),
- ("/32", Err(())),
- ];
- for &(s, cidr) in &tests {
- assert_eq!(Ipv4Cidr::from_str(s), cidr);
- assert_eq!(IpCidr::from_str(s), cidr.map(IpCidr::Ipv4));
- if let Ok(cidr) = cidr {
- assert_eq!(Ipv4Cidr::from_str(&format!("{}", cidr)), Ok(cidr));
- assert_eq!(IpCidr::from_str(&format!("{}", cidr)),
- Ok(IpCidr::Ipv4(cidr)));
- }
- }
- }
- }
|