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