|
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 |
|
@@ -143,6 +144,28 @@ pub trait LensExt<A: ?Sized, B: ?Sized>: Lens<A, B> {
|
143 | 144 | {
|
144 | 145 | self.then(Index::new(index))
|
145 | 146 | }
|
| 147 | + |
| 148 | + /// Adapt to operate on the contents of an `Arc` with efficient copy-on-write semantics |
| 149 | + /// |
| 150 | + /// ``` |
| 151 | + /// # use druid::*; use std::sync::Arc; |
| 152 | + /// let lens = lens::Id.index(2).in_arc(); |
| 153 | + /// let mut x = Arc::new(vec![0, 1, 2, 3]); |
| 154 | + /// let original = x.clone(); |
| 155 | + /// assert_eq!(lens.get(&x), 2); |
| 156 | + /// lens.put(&mut x, 2); |
| 157 | + /// assert!(Arc::ptr_eq(&original, &x), "no-op writes don't cause a deep copy"); |
| 158 | + /// lens.put(&mut x, 42); |
| 159 | + /// assert_eq!(&*x, &[0, 1, 42, 3]); |
| 160 | + /// ``` |
| 161 | + fn in_arc(self) -> InArc<Self> |
| 162 | + where |
| 163 | + A: Clone, |
| 164 | + B: Data, |
| 165 | + Self: Sized, |
| 166 | + { |
| 167 | + InArc::new(self) |
| 168 | + } |
146 | 169 | }
|
147 | 170 |
|
148 | 171 | impl<A: ?Sized, B: ?Sized, T: Lens<A, B>> LensExt<A, B> for T {}
|
@@ -441,3 +464,45 @@ impl<A: ?Sized> Lens<A, A> for Id {
|
441 | 464 | f(data)
|
442 | 465 | }
|
443 | 466 | }
|
| 467 | + |
| 468 | +/// A `Lens` that exposes data within an `Arc` with copy-on-write semantics |
| 469 | +/// |
| 470 | +/// A copy is only made in the event that a different value is written. |
| 471 | +#[derive(Debug, Copy, Clone)] |
| 472 | +pub struct InArc<L> { |
| 473 | + inner: L, |
| 474 | +} |
| 475 | + |
| 476 | +impl<L> InArc<L> { |
| 477 | + /// Adapt a lens to operate on an `Arc` |
| 478 | + /// |
| 479 | + /// See also `LensExt::in_arc` |
| 480 | + pub fn new<A, B>(inner: L) -> Self |
| 481 | + where |
| 482 | + A: Clone, |
| 483 | + B: Data, |
| 484 | + L: Lens<A, B>, |
| 485 | + { |
| 486 | + Self { inner } |
| 487 | + } |
| 488 | +} |
| 489 | + |
| 490 | +impl<A, B, L> Lens<Arc<A>, B> for InArc<L> |
| 491 | +where |
| 492 | + A: Clone, |
| 493 | + B: Data, |
| 494 | + L: Lens<A, B>, |
| 495 | +{ |
| 496 | + fn with<V, F: FnOnce(&B) -> V>(&self, data: &Arc<A>, f: F) -> V { |
| 497 | + self.inner.with(data, f) |
| 498 | + } |
| 499 | + |
| 500 | + fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut Arc<A>, f: F) -> V { |
| 501 | + let mut temp = self.inner.with(data, |x| x.clone()); |
| 502 | + let v = f(&mut temp); |
| 503 | + if self.inner.with(data, |x| !x.same(&temp)) { |
| 504 | + self.inner.with_mut(Arc::make_mut(data), |x| *x = temp); |
| 505 | + } |
| 506 | + v |
| 507 | + } |
| 508 | +} |
0 commit comments