|
16 | 16 |
|
17 | 17 | use std::marker::PhantomData;
|
18 | 18 | use std::ops;
|
| 19 | +use std::sync::Arc; |
19 | 20 |
|
20 | 21 | pub use druid_derive::Lens;
|
21 | 22 |
|
@@ -121,6 +122,28 @@ pub trait LensExt<A: ?Sized, B: ?Sized>: Lens<A, B> {
|
121 | 122 | {
|
122 | 123 | self.then(Index::new(index))
|
123 | 124 | }
|
| 125 | + |
| 126 | + /// Adapt to operate on the contents of an `Arc` with efficient copy-on-write semantics |
| 127 | + /// |
| 128 | + /// ``` |
| 129 | + /// # use druid::*; use std::sync::Arc; |
| 130 | + /// let lens = lens::Id.index(2).in_arc(); |
| 131 | + /// let mut x = Arc::new(vec![0, 1, 2, 3]); |
| 132 | + /// let original = x.clone(); |
| 133 | + /// assert_eq!(lens.get(&x), 2); |
| 134 | + /// lens.put(&mut x, 2); |
| 135 | + /// assert!(Arc::ptr_eq(&original, &x), "no-op writes don't cause a deep copy"); |
| 136 | + /// lens.put(&mut x, 42); |
| 137 | + /// assert_eq!(&*x, &[0, 1, 42, 3]); |
| 138 | + /// ``` |
| 139 | + fn in_arc(self) -> InArc<Self> |
| 140 | + where |
| 141 | + A: Clone, |
| 142 | + B: Data, |
| 143 | + Self: Sized, |
| 144 | + { |
| 145 | + InArc::new(self) |
| 146 | + } |
124 | 147 | }
|
125 | 148 |
|
126 | 149 | impl<A: ?Sized, B: ?Sized, T: Lens<A, B>> LensExt<A, B> for T {}
|
@@ -379,3 +402,45 @@ impl<A: ?Sized> Lens<A, A> for Id {
|
379 | 402 | f(data)
|
380 | 403 | }
|
381 | 404 | }
|
| 405 | + |
| 406 | +/// A `Lens` that exposes data within an `Arc` with copy-on-write semantics |
| 407 | +/// |
| 408 | +/// A copy is only made in the event that a different value is written. |
| 409 | +#[derive(Debug, Copy, Clone)] |
| 410 | +pub struct InArc<L> { |
| 411 | + inner: L, |
| 412 | +} |
| 413 | + |
| 414 | +impl<L> InArc<L> { |
| 415 | + /// Adapt a lens to operate on an `Arc` |
| 416 | + /// |
| 417 | + /// See also `LensExt::in_arc` |
| 418 | + pub fn new<A, B>(inner: L) -> Self |
| 419 | + where |
| 420 | + A: Clone, |
| 421 | + B: Data, |
| 422 | + L: Lens<A, B>, |
| 423 | + { |
| 424 | + Self { inner } |
| 425 | + } |
| 426 | +} |
| 427 | + |
| 428 | +impl<A, B, L> Lens<Arc<A>, B> for InArc<L> |
| 429 | +where |
| 430 | + A: Clone, |
| 431 | + B: Data, |
| 432 | + L: Lens<A, B>, |
| 433 | +{ |
| 434 | + fn with<V, F: FnOnce(&B) -> V>(&self, data: &Arc<A>, f: F) -> V { |
| 435 | + self.inner.with(data, f) |
| 436 | + } |
| 437 | + |
| 438 | + fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut Arc<A>, f: F) -> V { |
| 439 | + let mut temp = self.inner.with(data, |x| x.clone()); |
| 440 | + let v = f(&mut temp); |
| 441 | + if self.inner.with(data, |x| !x.same(&temp)) { |
| 442 | + self.inner.with_mut(Arc::make_mut(data), |x| *x = temp); |
| 443 | + } |
| 444 | + v |
| 445 | + } |
| 446 | +} |
0 commit comments