changeset 4:88dc74ffd497

Introduce panic-on-unreleased-drop while developing
author Lewin Bormann <lewin@lewin-bormann.info>
date Thu, 30 May 2019 11:35:11 +0200
parents ff95584ff3c9
children fe1259c95911
files src/combinators.rs src/primitives.rs src/state.rs
diffstat 3 files changed, 39 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/combinators.rs	Thu May 30 11:18:31 2019 +0200
+++ b/src/combinators.rs	Thu May 30 11:35:11 2019 +0200
@@ -88,7 +88,7 @@
 
     #[test]
     fn test_long_seq() {
-        let s = (|| StringParser::new("a"));
+        let s = || StringParser::new("a");
         let mut p = Sequence::new((s(), s(), s(), s(), s(), s(), s(), s(), s(), s()));
         let mut ps = ParseState::new("aaaaaaaaaa");
         assert_eq!(
--- a/src/primitives.rs	Thu May 30 11:18:31 2019 +0200
+++ b/src/primitives.rs	Thu May 30 11:35:11 2019 +0200
@@ -4,7 +4,9 @@
 pub struct StringParser(String);
 
 impl StringParser {
-    pub fn new<S: AsRef<str>>(s: S) -> StringParser { StringParser(s.as_ref().to_owned()) }
+    pub fn new<S: AsRef<str>>(s: S) -> StringParser {
+        StringParser(s.as_ref().to_owned())
+    }
 }
 
 impl Parser for StringParser {
--- a/src/state.rs	Thu May 30 11:18:31 2019 +0200
+++ b/src/state.rs	Thu May 30 11:35:11 2019 +0200
@@ -28,7 +28,28 @@
     // TODO: Implement garbage collection on `buf`
 }
 
-pub struct Hold(usize);
+pub struct Hold {
+    ix: usize,
+    released: bool,
+}
+
+impl Hold {
+    fn new(ix: usize) -> Hold {
+        Hold {
+            ix: ix,
+            released: false,
+        }
+    }
+    fn defuse(&mut self) {
+        self.released = true;
+    }
+}
+
+impl Drop for Hold {
+    fn drop(&mut self) {
+        assert!(self.released, "Dropped unreleased hold! This is a bug");
+    }
+}
 
 impl<'a> ParseState<Chars<'a>> {
     pub fn new(s: &'a str) -> ParseState<Chars<'a>> {
@@ -53,13 +74,15 @@
         self.current
     }
     pub fn hold(&mut self) -> Hold {
-        Hold(self.current)
+        Hold::new(self.current)
     }
-    pub fn release(&mut self, _h: Hold) {
+    pub fn release(&mut self, mut h: Hold) {
         // TODO: Implement when hold tracking is needed (for garbage collection).
+        h.defuse();
     }
-    pub fn reset(&mut self, h: Hold) {
-        self.current = h.0;
+    pub fn reset(&mut self, mut h: Hold) {
+        self.current = h.ix;
+        h.defuse();
     }
     pub fn finished(&self) -> bool {
         self.next.is_none() && self.current == self.buf.len()
@@ -142,6 +165,13 @@
         assert_eq!("Hello", rest);
     }
 
+    #[test]
+    #[should_panic]
+    fn test_hold_unreleased() {
+        let mut s = ParseState::new("abcde");
+        let _hold = s.hold();
+    }
+
     use crate::primitives;
 
     #[test]