1#[macro_export]
36macro_rules! with {
37 (mut $obj:expr => $($body:tt)*) => ({
39 let mut obj = $obj;
40 $crate::with!(@parse obj $($body)*);
41 obj
42 });
43
44 ($obj:expr => $($body:tt)*) => ({
46 let obj = $obj;
47 $crate::with!(@parse obj $($body)*);
48 obj
49 });
50
51 (@parse $obj:ident) => ();
53
54 (@parse $obj:ident . $method:ident ( $($args:expr),* ) $($tail:tt)*) => {
56 $obj.$method($($args),*);
57 $crate::with!(@parse $obj $($tail)*)
58 };
59
60 (@parse $obj:ident let $var:pat = . $method:ident ( $($args:expr),* ) ; $($tail:tt)*) => {
62 let $var = $obj.$method($($args),*);
63 $crate::with!(@parse $obj $($tail)*)
64 };
65
66 (@parse $obj:ident $var:ident = . $method:ident ( $($args:expr),* ) ; $($tail:tt)*) => {
68 $var = $obj.$method($($args),*);
69 $crate::with!(@parse $obj $($tail)*)
70 };
71
72 (@parse $obj:ident $exp:expr ; $($tail:tt)*) => {
74 $exp;
75 $crate::with!(@parse $obj $($tail)*)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use std::cell::Cell;
82
83 #[derive(Debug, PartialEq, Eq)]
84 struct Foo(Cell<i32>);
85
86 impl Foo {
87 fn new(val: i32) -> Self {
88 Foo(Cell::new(val))
89 }
90
91 fn get_val(&self) -> i32 {
92 self.0.get()
93 }
94
95 fn set_val(&self, val: i32) {
96 self.0.set(val)
97 }
98
99 fn add(&self, n: i32) {
100 self.0.set(self.0.get() + n)
101 }
102
103 fn mul(&self, n: i32) {
104 self.0.set(self.0.get() * n)
105 }
106 }
107
108 #[test]
109 fn basic() {
110 let a;
111 let foo = with! {
112 Foo::new(0) =>
113 .set_val(10)
114 .mul(2)
115 a = .get_val();
116 .add(1)
117 let n = .get_val();
118 assert_eq!(n, 21);
119 .mul(2)
120 };
121
122 assert_eq!(a, 20);
123 assert_eq!(foo.get_val(), 42);
124 }
125
126 #[test]
127 fn mutable() {
128 let vec = with! {
129 mut Vec::new() =>
130 .push(1)
131 .push(42)
132 .push(-13)
133 let l = .len();
134 assert_eq!(l, 3);
135 };
136
137 assert_eq!(vec, [1, 42, -13]);
138 }
139
140 #[test]
141 fn nested() {
142 let vec = with! {
143 mut Vec::new() =>
144 .push(with!{
145 Foo::new(3) =>
146 })
147 .push(with!{
148 Foo::new(0) =>
149 .set_val(10)
150 .add(3)
151 })
152 };
153
154 assert_eq!(vec, [Foo::new(3), Foo::new(13)]);
155 }
156}