We have these RAII/transaction things:
struct SubtreeHelper<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> where Self: 'r {
root: &'r mut Parser<'s, P, O, T>,
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> SubtreeHelper<'r, 's, P, O, T> where Self: 'r {
fn start(value: &'r mut Parser<'s, P, O, T>) -> Self {
value.consts.protos.push(Default::default());
Self {
root: value,
}
}
fn commit(self) -> usize {
let mut self_ = ManuallyDrop::new(self);
let proto = self_.root.consts.protos.pop().unwrap();
let id = self_.root.closed_subtrees.next().unwrap();
self_.root.consts.protos.insert(id, proto);
id
}
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> std::ops::Deref for SubtreeHelper<'r, 's, P, O, T> where Self: 'r {
type Target = Parser<'s, P, O, T>;
fn deref(&self) -> &Self::Target {
&*self.root
}
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> std::ops::DerefMut for SubtreeHelper<'r, 's, P, O, T> where Self: 'r {
fn deref_mut(&mut self) -> &mut Self::Target {
self.root
}
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> Drop for SubtreeHelper<'r, 's, P, O, T> where Self: 'r {
fn drop(&mut self) {
// remove "partial" proto
self.root.consts.protos.pop().expect("SubtreeHelper");
}
}
struct TagHelper<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> where Self: 'r {
root: &'r mut Parser<'s, P, O, T>,
len: usize,
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> TagHelper<'r, 's, P, O, T> where Self: 'r {
fn start(value: &'r mut Parser<'s, P, O, T>) -> Self {
let len = value.consts.protos.last().unwrap().len();
Self {
root: value,
len : len,
}
}
fn commit(self) {
std::mem::forget(self)
}
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> std::ops::Deref for TagHelper<'r, 's, P, O, T> where Self: 'r {
type Target = Parser<'s, P, O, T>;
fn deref(&self) -> &Self::Target {
&*self.root
}
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> std::ops::DerefMut for TagHelper<'r, 's, P, O, T> where Self: 'r {
fn deref_mut(&mut self) -> &mut Self::Target {
self.root
}
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> Drop for TagHelper<'r, 's, P, O, T> where Self: 'r {
fn drop(&mut self) {
let proto = self.root.consts.protos.last_mut().unwrap();
assert!(proto.len() >= self.len);
while proto.len() > self.len {
let _ = proto.pop();
}
}
}
They come with a lot of generics. This is less than ideal. Since Drop
can't be specialized there's really no good way to get rid of the pointless generics for Deref
and DerefMut
. So ofc the next solution is to get rid of all of them. :p
It'd be cool to just do this:
struct SubtreeHelper<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> where Self: 'r {
root: &'r mut Parser<'s, P, O, T>,
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> SubtreeHelper<'r, 's, P, O, T> where Self: 'r {
fn start(value: &'r mut Parser<'s, P, O, T>) -> Self {
value.consts.protos.push(Default::default());
Self {
root: value,
}
}
fn commit(self) -> usize {
let mut self_ = ManuallyDrop::new(self);
let proto = self_.root.consts.protos.pop().unwrap();
let id = self_.root.closed_subtrees.next().unwrap();
self_.root.consts.protos.insert(id, proto);
id
}
impl std::ops::Deref {
type Target = Parser<'s, P, O, T>;
fn deref(&self) -> &Self::Target {
&*self.root
}
}
impl std::ops::DerefMut {
fn deref_mut(&mut self) -> &mut Self::Target {
self.root
}
}
impl Drop {
fn drop(&mut self) {
// remove "partial" proto
self.root.consts.protos.pop().expect("SubtreeHelper");
}
}
}
struct TagHelper<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> where Self: 'r {
root: &'r mut Parser<'s, P, O, T>,
len: usize,
}
impl<'r, 's, P: Borrow<str> + Ord, O: Borrow<str> + Ord, T: PatternTypes> TagHelper<'r, 's, P, O, T> where Self: 'r {
fn start(value: &'r mut Parser<'s, P, O, T>) -> Self {
let len = value.consts.protos.last().unwrap().len();
Self {
root: value,
len : len,
}
}
fn commit(self) {
std::mem::forget(self)
}
impl std::ops::Deref {
type Target = Parser<'s, P, O, T>;
fn deref(&self) -> &Self::Target {
&*self.root
}
}
impl std::ops::DerefMut {
fn deref_mut(&mut self) -> &mut Self::Target {
self.root
}
}
impl Drop {
fn drop(&mut self) {
let proto = self.root.consts.protos.last_mut().unwrap();
assert!(proto.len() >= self.len);
while proto.len() > self.len {
let _ = proto.pop();
}
}
}
}