parsers.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. use core::str::FromStr;
  2. use core::result;
  3. use wire::{EthernetAddress, IpAddress, Ipv4Address, Ipv4Cidr, IpCidr};
  4. type Result<T> = result::Result<T, ()>;
  5. struct Parser<'a> {
  6. data: &'a [u8],
  7. pos: usize
  8. }
  9. impl<'a> Parser<'a> {
  10. fn new(data: &'a str) -> Parser<'a> {
  11. Parser {
  12. data: data.as_bytes(),
  13. pos: 0
  14. }
  15. }
  16. fn advance(&mut self) -> Result<u8> {
  17. match self.data.get(self.pos) {
  18. Some(&chr) => {
  19. self.pos += 1;
  20. Ok(chr)
  21. }
  22. None => Err(())
  23. }
  24. }
  25. fn try<F, T>(&mut self, f: F) -> Option<T>
  26. where F: FnOnce(&mut Parser<'a>) -> Result<T> {
  27. let pos = self.pos;
  28. match f(self) {
  29. Ok(res) => Some(res),
  30. Err(()) => {
  31. self.pos = pos;
  32. None
  33. }
  34. }
  35. }
  36. fn accept_eof(&mut self) -> Result<()> {
  37. if self.data.len() == self.pos {
  38. Ok(())
  39. } else {
  40. Err(())
  41. }
  42. }
  43. fn until_eof<F, T>(&mut self, f: F) -> Result<T>
  44. where F: FnOnce(&mut Parser<'a>) -> Result<T> {
  45. let res = f(self)?;
  46. self.accept_eof()?;
  47. Ok(res)
  48. }
  49. fn accept_char(&mut self, chr: u8) -> Result<()> {
  50. if self.advance()? == chr {
  51. Ok(())
  52. } else {
  53. Err(())
  54. }
  55. }
  56. fn accept_digit(&mut self, hex: bool) -> Result<u8> {
  57. let digit = self.advance()?;
  58. if digit >= b'0' && digit <= b'9' {
  59. Ok(digit - b'0')
  60. } else if hex && digit >= b'a' && digit <= b'f' {
  61. Ok(digit - b'a' + 10)
  62. } else if hex && digit >= b'A' && digit <= b'F' {
  63. Ok(digit - b'A' + 10)
  64. } else {
  65. Err(())
  66. }
  67. }
  68. fn accept_number(&mut self, max_digits: usize, max_value: u32,
  69. hex: bool) -> Result<u32> {
  70. let mut value = self.accept_digit(hex)? as u32;
  71. for _ in 1..max_digits {
  72. match self.try(|p| p.accept_digit(hex)) {
  73. Some(digit) => {
  74. value *= if hex { 16 } else { 10 };
  75. value += digit as u32;
  76. }
  77. None => break
  78. }
  79. }
  80. if value < max_value {
  81. Ok(value)
  82. } else {
  83. Err(())
  84. }
  85. }
  86. fn accept_mac_joined_with(&mut self, separator: u8) -> Result<EthernetAddress> {
  87. let mut octets = [0u8; 6];
  88. for n in 0..6 {
  89. octets[n] = self.accept_number(2, 0x100, true)? as u8;
  90. if n != 5 {
  91. self.accept_char(separator)?;
  92. }
  93. }
  94. Ok(EthernetAddress(octets))
  95. }
  96. fn accept_mac(&mut self) -> Result<EthernetAddress> {
  97. if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b'-')) {
  98. return Ok(mac)
  99. }
  100. if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b':')) {
  101. return Ok(mac)
  102. }
  103. Err(())
  104. }
  105. fn accept_ipv4(&mut self) -> Result<Ipv4Address> {
  106. let mut octets = [0u8; 4];
  107. for n in 0..4 {
  108. octets[n] = self.accept_number(3, 0x100, false)? as u8;
  109. if n != 3 {
  110. self.accept_char(b'.')?;
  111. }
  112. }
  113. Ok(Ipv4Address(octets))
  114. }
  115. fn accept_ip(&mut self) -> Result<IpAddress> {
  116. if let Some(ipv4) = self.try(|p| p.accept_ipv4()) {
  117. return Ok(IpAddress::Ipv4(ipv4))
  118. }
  119. Err(())
  120. }
  121. }
  122. impl FromStr for EthernetAddress {
  123. type Err = ();
  124. /// Parse a string representation of an Ethernet address.
  125. fn from_str(s: &str) -> Result<EthernetAddress> {
  126. Parser::new(s).until_eof(|p| p.accept_mac())
  127. }
  128. }
  129. impl FromStr for Ipv4Address {
  130. type Err = ();
  131. /// Parse a string representation of an IPv4 address.
  132. fn from_str(s: &str) -> Result<Ipv4Address> {
  133. Parser::new(s).until_eof(|p| p.accept_ipv4())
  134. }
  135. }
  136. impl FromStr for IpAddress {
  137. type Err = ();
  138. /// Parse a string representation of an IP address.
  139. fn from_str(s: &str) -> Result<IpAddress> {
  140. Parser::new(s).until_eof(|p| p.accept_ip())
  141. }
  142. }
  143. impl FromStr for Ipv4Cidr {
  144. type Err = ();
  145. /// Parse a string representation of an IPv4 CIDR.
  146. fn from_str(s: &str) -> Result<Ipv4Cidr> {
  147. Parser::new(s).until_eof(|p| {
  148. let ip = p.accept_ipv4()?;
  149. p.accept_char(b'/')?;
  150. let prefix_len = p.accept_number(2, 33, false)? as u8;
  151. Ok(Ipv4Cidr::new(ip, prefix_len))
  152. })
  153. }
  154. }
  155. impl FromStr for IpCidr {
  156. type Err = ();
  157. /// Parse a string representation of an IP CIDR.
  158. fn from_str(s: &str) -> Result<IpCidr> {
  159. Ipv4Cidr::from_str(s).map(IpCidr::Ipv4)
  160. }
  161. }
  162. #[cfg(test)]
  163. mod test {
  164. use super::*;
  165. #[test]
  166. fn test_mac() {
  167. assert_eq!(EthernetAddress::from_str(""), Err(()));
  168. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"),
  169. Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00])));
  170. assert_eq!(EthernetAddress::from_str("01:23:45:67:89:ab"),
  171. Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab])));
  172. assert_eq!(EthernetAddress::from_str("cd:ef:10:00:00:00"),
  173. Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00])));
  174. assert_eq!(EthernetAddress::from_str("00:00:00:ab:cd:ef"),
  175. Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
  176. assert_eq!(EthernetAddress::from_str("00-00-00-ab-cd-ef"),
  177. Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
  178. assert_eq!(EthernetAddress::from_str("AB-CD-EF-00-00-00"),
  179. Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00])));
  180. assert_eq!(EthernetAddress::from_str("100:00:00:00:00:00"), Err(()));
  181. assert_eq!(EthernetAddress::from_str("002:00:00:00:00:00"), Err(()));
  182. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:000"), Err(()));
  183. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:0x"), Err(()));
  184. }
  185. #[test]
  186. fn test_ipv4() {
  187. assert_eq!(Ipv4Address::from_str(""), Err(()));
  188. assert_eq!(Ipv4Address::from_str("1.2.3.4"),
  189. Ok(Ipv4Address([1, 2, 3, 4])));
  190. assert_eq!(Ipv4Address::from_str("001.2.3.4"),
  191. Ok(Ipv4Address([1, 2, 3, 4])));
  192. assert_eq!(Ipv4Address::from_str("0001.2.3.4"), Err(()));
  193. assert_eq!(Ipv4Address::from_str("999.2.3.4"), Err(()));
  194. assert_eq!(Ipv4Address::from_str("1.2.3.4.5"), Err(()));
  195. assert_eq!(Ipv4Address::from_str("1.2.3"), Err(()));
  196. assert_eq!(Ipv4Address::from_str("1.2.3."), Err(()));
  197. assert_eq!(Ipv4Address::from_str("1.2.3.4."), Err(()));
  198. }
  199. #[test]
  200. fn test_ip() {
  201. assert_eq!(IpAddress::from_str(""), Err(()));
  202. assert_eq!(IpAddress::from_str("1.2.3.4"),
  203. Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4]))));
  204. assert_eq!(IpAddress::from_str("x"), Err(()));
  205. }
  206. #[test]
  207. fn test_cidr() {
  208. let tests = [
  209. ("127.0.0.1/8",
  210. Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8))),
  211. ("192.168.1.1/24",
  212. Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8))),
  213. ("8.8.8.8/32",
  214. Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8))),
  215. ("8.8.8.8/0",
  216. Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8))),
  217. ("", Err(())),
  218. ("1", Err(())),
  219. ("127.0.0.1", Err(())),
  220. ("127.0.0.1/", Err(())),
  221. ("127.0.0.1/33", Err(())),
  222. ("127.0.0.1/111", Err(())),
  223. ("/32", Err(())),
  224. ];
  225. for &(s, cidr) in &tests {
  226. assert_eq!(Ipv4Cidr::from_str(s), cidr);
  227. assert_eq!(IpCidr::from_str(s), cidr.map(IpCidr::Ipv4));
  228. if let Ok(cidr) = cidr {
  229. assert_eq!(Ipv4Cidr::from_str(&format!("{}", cidr)), Ok(cidr));
  230. assert_eq!(IpCidr::from_str(&format!("{}", cidr)),
  231. Ok(IpCidr::Ipv4(cidr)));
  232. }
  233. }
  234. }
  235. }