Advertisement
Guest User

Untitled

a guest
Jun 27th, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.26 KB | None | 0 0
  1. fn main() {
  2. let inputs = &["foo; bar; baz", "foo;", ";foo"];
  3. for input in inputs {
  4. println!("qas: {:?}", quote_aware_split(input, ";").collect::<Vec<_>>());
  5. println!("std: {:?}", input.split(';').collect::<Vec<_>>());
  6. }
  7. }
  8.  
  9.  
  10. fn quote_aware_split<'a>(input: &'a str, split: &'a str) -> QuoteAwareSplit<'a> {
  11. QuoteAwareSplit { haystack: input, needle: split, fused: false }
  12. }
  13.  
  14. pub struct QuoteAwareSplit<'a> {
  15. haystack: &'a str, // the text being searched
  16. needle: &'a str, // the text being searched for
  17. fused: bool // if we've consumed the haystack and no more results should be returned
  18. }
  19.  
  20. impl<'a> QuoteAwareSplit<'a> {
  21. pub fn remainder(&mut self) -> &str {
  22. let haystack = self.haystack;
  23. self.haystack = "";
  24. self.fused = true;
  25. haystack
  26. }
  27. }
  28.  
  29. impl<'a> Iterator for QuoteAwareSplit<'a> {
  30. type Item = &'a str;
  31.  
  32. fn next(&mut self) -> Option<Self::Item> {
  33. let (l, r, o) = self.next_idx()?;
  34.  
  35. if l == 0 && r == 0 && o == 0 {
  36. self.fused = true;
  37. return Some("");
  38. }
  39.  
  40. let ret = &self.haystack[l..r];
  41. self.haystack = &self.haystack[r+o..];
  42. return Some(ret);
  43. }
  44. }
  45.  
  46. impl<'a> QuoteAwareSplit<'a> {
  47. // (left_ptr, right_ptr, right_advance_offset)
  48. fn next_idx(&self) -> Option<(usize, usize, usize)> {
  49. let mut in_escape = false;
  50. let mut in_quote = false;
  51.  
  52. if self.fused {
  53. return None;
  54. }
  55.  
  56. if self.haystack.is_empty() {
  57. return Some((0, 0, 0));
  58. }
  59.  
  60. if self.needle.is_empty() {
  61. return Some((0, self.haystack.len(), 0));
  62. }
  63.  
  64. let needle_first = self.needle.chars().next().unwrap();
  65.  
  66. for (i, c) in self.haystack.chars().enumerate() {
  67. // if we're in an unescaped quote/string, don't look for needle
  68. if c == '"' { // double-quote character
  69. if in_escape {
  70. in_escape = false;
  71. } else {
  72. in_quote = !in_quote;
  73. }
  74. } else if c == '\\' {
  75. in_escape = !in_escape;
  76. } else if in_escape {
  77. in_escape = false;
  78. }
  79.  
  80. if !in_quote && c == needle_first {
  81. let needle_len = self.needle.len();
  82. if needle_len + i > self.haystack.len() {
  83. break;
  84. }
  85. if &self.haystack[i..i+needle_len] == self.needle {
  86. return Some((0, i, needle_len));
  87. }
  88. }
  89. }
  90.  
  91. return Some((0, self.haystack.len(), 0));
  92. }
  93.  
  94. pub fn peek(&self) -> Option<&str> {
  95. self.next_idx().map(|(l, r, _)| &self.haystack[l..r])
  96. }
  97. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement