1#![no_std]
55#![deny(rust_2018_idioms)]
57
58#[cfg(any(test, feature = "std"))]
59extern crate std;
60
61extern crate alloc;
62
63mod context;
64#[cfg(do_cycle_debug)]
65mod cycle_debug;
66mod queue;
67mod sync;
68mod trigger;
69mod watched_core;
70mod watcher;
71
72pub use crate::{
73 context::{DefaultOwner, WatchContext},
74 queue::WatchedQueue,
75 sync::{
76 watched_channel, SendGuard, SyncTrigger, SyncWatchedMeta,
77 WatchedReceiver, WatchedSender,
78 },
79 trigger::{RawWatchArg, WatchArg, WatchName},
80 watched_core::{
81 WatchedCellCore, WatchedCore, WatchedMeta, WatchedValueCore,
82 },
83 watcher::{Watcher, WatcherHolder, WatcherInit},
84};
85
86#[cfg(feature = "std")]
87mod watched;
88#[cfg(feature = "std")]
89pub use crate::watched::{Watched, WatchedCell, WatchedValue};
90
91#[doc = include_str!("../README.md")]
92#[cfg(doctest)]
93pub struct ReadmeDoctests;
94
95#[cfg(all(test, feature = "std"))]
96mod tests {
97 use std::{cell::RefCell, rc::Rc};
98
99 use super::*;
100
101 #[test]
102 fn simple_propogate_core() {
103 struct Content {
104 dest: i32,
105 source: WatchedCore<'static, i32>,
106 }
107
108 impl Watcher<'static> for Content {
109 fn init(mut init: impl WatcherInit<'static, Self>) {
110 init.watch_explicit(|arg, root| {
111 root.dest = *root.source.get(arg);
112 });
113 }
114 }
115 let content = Rc::new(RefCell::new(Content {
116 dest: 0,
117 source: WatchedCore::new(37),
118 }));
119 let weak = Rc::downgrade(&content);
120
121 let mut ctx = WatchContext::new();
122 assert_eq!(content.borrow().dest, 0);
123 ctx.add_watcher(&weak);
124 assert_eq!(content.borrow().dest, 37);
125 *content.borrow_mut().source.get_mut_external() = 43;
126 assert_eq!(content.borrow().dest, 37);
127 ctx.update();
128 assert_eq!(content.borrow().dest, 43);
129 ctx.update();
130 assert_eq!(content.borrow().dest, 43);
131 }
132
133 #[test]
134 fn simple_propogate() {
135 struct Content {
136 dest: i32,
137 source: Watched<i32>,
138 }
139
140 impl Watcher<'static> for Content {
141 fn init(mut init: impl WatcherInit<'static, Self>) {
142 init.watch(|root| {
143 root.dest = *root.source;
144 });
145 }
146 }
147 let content = Rc::new(RefCell::new(Content {
148 dest: 0,
149 source: Watched::new(37),
150 }));
151 let weak = Rc::downgrade(&content);
152
153 let mut ctx = WatchContext::new();
154 assert_eq!(content.borrow().dest, 0);
155 ctx.add_watcher(&weak);
156 assert_eq!(content.borrow().dest, 37);
157 *content.borrow_mut().source = 43;
158 assert_eq!(content.borrow().dest, 37);
159 ctx.update();
160 assert_eq!(content.borrow().dest, 43);
161 ctx.update();
162 assert_eq!(content.borrow().dest, 43);
163 }
164
165 #[test]
166 fn double_mut_in_watch() {
167 #[derive(Default)]
168 struct MutsTwice {
169 value: Watched<i32>,
170 }
171
172 impl Watcher<'static> for MutsTwice {
173 fn init(mut init: impl WatcherInit<'static, Self>) {
174 init.watch(|root| {
175 root.value += 1;
176 root.value += 1;
177 });
178 }
179 }
180
181 let content = Rc::new(RefCell::new(MutsTwice {
182 value: Watched::new(0_i32),
183 }));
184 let weak = Rc::downgrade(&content);
185
186 let mut ctx = WatchContext::new();
187 ctx.set_frame_limit(Some(100));
188 ctx.add_watcher(&weak);
189 assert_eq!(*content.borrow().value, 2);
190 ctx.update();
191 assert_eq!(*content.borrow().value, 2);
192 *content.borrow_mut().value = 41;
193 ctx.update();
194 assert_eq!(*content.borrow().value, 43);
195 }
196
197 #[test]
198 fn send_received_by_watch() {
199 use std::sync::mpsc::{channel, Receiver};
200
201 struct Content {
202 dest: Option<i32>,
203 source: WatchedReceiver<Receiver<i32>>,
204 }
205
206 impl Watcher<'static> for Content {
207 fn init(mut init: impl WatcherInit<'static, Self>) {
208 init.watch_explicit(|arg, root| {
209 root.dest = root.source.get(arg).try_recv().ok();
210 });
211 }
212 }
213
214 let (sender, receiver) = watched_channel(channel());
215
216 let content = Rc::new(RefCell::new(Content {
217 dest: None,
218 source: receiver,
219 }));
220 let weak = Rc::downgrade(&content);
221
222 let mut ctx = WatchContext::new();
223 ctx.add_watcher(&weak);
224 assert_eq!(content.borrow().dest, None);
225 let thread_handle = std::thread::spawn(move || {
226 sender.sender().send(4812).unwrap();
227 });
228 thread_handle.join().unwrap();
229 ctx.update();
230 assert_eq!(content.borrow().dest, Some(4812));
231 }
232}