parsers.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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(()) = self.try(|p| p.accept_eof()) {
  117. return Ok(IpAddress::Unspecified)
  118. }
  119. if let Some(ipv4) = self.try(|p| p.accept_ipv4()) {
  120. return Ok(IpAddress::Ipv4(ipv4))
  121. }
  122. Err(())
  123. }
  124. }
  125. impl FromStr for EthernetAddress {
  126. type Err = ();
  127. /// Parse a string representation of an Ethernet address.
  128. fn from_str(s: &str) -> Result<EthernetAddress> {
  129. Parser::new(s).until_eof(|p| p.accept_mac())
  130. }
  131. }
  132. impl FromStr for Ipv4Address {
  133. type Err = ();
  134. /// Parse a string representation of an IPv4 address.
  135. fn from_str(s: &str) -> Result<Ipv4Address> {
  136. Parser::new(s).until_eof(|p| p.accept_ipv4())
  137. }
  138. }
  139. impl FromStr for IpAddress {
  140. type Err = ();
  141. /// Parse a string representation of an IPv4 address.
  142. fn from_str(s: &str) -> Result<IpAddress> {
  143. Parser::new(s).until_eof(|p| p.accept_ip())
  144. }
  145. }
  146. impl FromStr for Ipv4Cidr {
  147. type Err = ();
  148. /// Parse a string representation of an IPv4 CIDR.
  149. fn from_str(s: &str) -> Result<Ipv4Cidr> {
  150. Parser::new(s).until_eof(|p| {
  151. let ip = p.accept_ipv4()?;
  152. p.accept_char(b'/')?;
  153. let prefix_len = p.accept_number(2, 33, false)? as u8;
  154. Ok(Ipv4Cidr::new(ip, prefix_len))
  155. })
  156. }
  157. }
  158. impl FromStr for IpCidr {
  159. type Err = ();
  160. /// Parse a string representation of an IP CIDR.
  161. fn from_str(s: &str) -> Result<IpCidr> {
  162. Ipv4Cidr::from_str(s).map(IpCidr::Ipv4)
  163. }
  164. }
  165. #[cfg(test)]
  166. mod test {
  167. use super::*;
  168. #[test]
  169. fn test_mac() {
  170. assert_eq!(EthernetAddress::from_str(""), Err(()));
  171. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"),
  172. Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00])));
  173. assert_eq!(EthernetAddress::from_str("01:23:45:67:89:ab"),
  174. Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab])));
  175. assert_eq!(EthernetAddress::from_str("cd:ef:10:00:00:00"),
  176. Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00])));
  177. assert_eq!(EthernetAddress::from_str("00:00:00:ab:cd:ef"),
  178. Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
  179. assert_eq!(EthernetAddress::from_str("00-00-00-ab-cd-ef"),
  180. Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
  181. assert_eq!(EthernetAddress::from_str("AB-CD-EF-00-00-00"),
  182. Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00])));
  183. assert_eq!(EthernetAddress::from_str("100:00:00:00:00:00"), Err(()));
  184. assert_eq!(EthernetAddress::from_str("002:00:00:00:00:00"), Err(()));
  185. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:000"), Err(()));
  186. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:0x"), Err(()));
  187. }
  188. #[test]
  189. fn test_ipv4() {
  190. assert_eq!(Ipv4Address::from_str(""), Err(()));
  191. assert_eq!(Ipv4Address::from_str("1.2.3.4"),
  192. Ok(Ipv4Address([1, 2, 3, 4])));
  193. assert_eq!(Ipv4Address::from_str("001.2.3.4"),
  194. Ok(Ipv4Address([1, 2, 3, 4])));
  195. assert_eq!(Ipv4Address::from_str("0001.2.3.4"), Err(()));
  196. assert_eq!(Ipv4Address::from_str("999.2.3.4"), Err(()));
  197. assert_eq!(Ipv4Address::from_str("1.2.3.4.5"), Err(()));
  198. assert_eq!(Ipv4Address::from_str("1.2.3"), Err(()));
  199. assert_eq!(Ipv4Address::from_str("1.2.3."), Err(()));
  200. assert_eq!(Ipv4Address::from_str("1.2.3.4."), Err(()));
  201. }
  202. #[test]
  203. fn test_ip() {
  204. assert_eq!(IpAddress::from_str(""),
  205. Ok(IpAddress::Unspecified));
  206. assert_eq!(IpAddress::from_str("1.2.3.4"),
  207. Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4]))));
  208. assert_eq!(IpAddress::from_str("x"), Err(()));
  209. }
  210. #[test]
  211. fn test_cidr() {
  212. let tests = [
  213. ("127.0.0.1/8",
  214. Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8))),
  215. ("192.168.1.1/24",
  216. Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8))),
  217. ("8.8.8.8/32",
  218. Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8))),
  219. ("8.8.8.8/0",
  220. Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8))),
  221. ("", Err(())),
  222. ("1", Err(())),
  223. ("127.0.0.1", Err(())),
  224. ("127.0.0.1/", Err(())),
  225. ("127.0.0.1/33", Err(())),
  226. ("127.0.0.1/111", Err(())),
  227. ("/32", Err(())),
  228. ];
  229. for &(s, cidr) in &tests {
  230. assert_eq!(Ipv4Cidr::from_str(s), cidr);
  231. assert_eq!(IpCidr::from_str(s), cidr.map(IpCidr::Ipv4));
  232. if let Ok(cidr) = cidr {
  233. assert_eq!(Ipv4Cidr::from_str(&format!("{}", cidr)), Ok(cidr));
  234. assert_eq!(IpCidr::from_str(&format!("{}", cidr)),
  235. Ok(IpCidr::Ipv4(cidr)));
  236. }
  237. }
  238. }
  239. }