From 1af8f56e89113802c209158dc46b6ec34b6386e0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 7 Feb 2024 08:53:21 -0600 Subject: [PATCH] make target an associated type --- packages/generational-box/src/lib.rs | 11 +- packages/generational-box/src/sync.rs | 2 +- packages/generational-box/src/unsync.rs | 2 +- packages/signals/src/copy_value.rs | 16 ++- packages/signals/src/global/memo.rs | 10 +- packages/signals/src/global/signal.rs | 25 ++-- packages/signals/src/map.rs | 153 +++++++++++------------ packages/signals/src/read.rs | 47 ++++--- packages/signals/src/read_only_signal.rs | 10 +- packages/signals/src/signal.rs | 23 ++-- packages/signals/src/write.rs | 47 ++++--- 11 files changed, 194 insertions(+), 152 deletions(-) diff --git a/packages/generational-box/src/lib.rs b/packages/generational-box/src/lib.rs index 052f95a37..341ef89bf 100644 --- a/packages/generational-box/src/lib.rs +++ b/packages/generational-box/src/lib.rs @@ -228,9 +228,9 @@ pub trait Storage: AnyStorage + 'static { /// A trait for any storage backing type. pub trait AnyStorage: Default { /// The reference this storage type returns. - type Ref: Deref; + type Ref: Deref + 'static; /// The mutable reference this storage type returns. - type Mut: DerefMut; + type Mut: DerefMut + 'static; /// Try to map the mutable ref. fn try_map_mut( @@ -247,13 +247,16 @@ pub trait AnyStorage: Default { } /// Try to map the ref. - fn try_map( + fn try_map( ref_: Self::Ref, f: impl FnOnce(&T) -> Option<&U>, ) -> Option>; /// Map the ref. - fn map(ref_: Self::Ref, f: impl FnOnce(&T) -> &U) -> Self::Ref { + fn map( + ref_: Self::Ref, + f: impl FnOnce(&T) -> &U, + ) -> Self::Ref { Self::try_map(ref_, |v| Some(f(v))).unwrap() } diff --git a/packages/generational-box/src/sync.rs b/packages/generational-box/src/sync.rs index 5241fb22e..1edd9a12e 100644 --- a/packages/generational-box/src/sync.rs +++ b/packages/generational-box/src/sync.rs @@ -23,7 +23,7 @@ impl AnyStorage for SyncStorage { type Ref = GenerationalRef>; type Mut = GenerationalRefMut>; - fn try_map( + fn try_map( ref_: Self::Ref, f: impl FnOnce(&I) -> Option<&U>, ) -> Option> { diff --git a/packages/generational-box/src/unsync.rs b/packages/generational-box/src/unsync.rs index e1f5f9df9..da08cf4c4 100644 --- a/packages/generational-box/src/unsync.rs +++ b/packages/generational-box/src/unsync.rs @@ -92,7 +92,7 @@ impl AnyStorage for UnsyncStorage { type Ref = GenerationalRef>; type Mut = GenerationalRefMut>; - fn try_map( + fn try_map( _self: Self::Ref, f: impl FnOnce(&I) -> Option<&U>, ) -> Option> { diff --git a/packages/signals/src/copy_value.rs b/packages/signals/src/copy_value.rs index 142e6d800..bf52d090c 100644 --- a/packages/signals/src/copy_value.rs +++ b/packages/signals/src/copy_value.rs @@ -204,14 +204,18 @@ impl> CopyValue { } } -impl> Readable for CopyValue { +impl> Readable for CopyValue { + type Target = T; type Ref = S::Ref; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { S::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { @@ -227,17 +231,17 @@ impl> Readable for CopyValue { } } -impl> Writable for CopyValue { +impl> Writable for CopyValue { type Mut = S::Mut; - fn map_mut &mut U>( + fn map_mut &mut U>( mut_: Self::Mut, f: F, ) -> Self::Mut { S::map_mut(mut_, f) } - fn try_map_mut Option<&mut U>>( + fn try_map_mut Option<&mut U>>( mut_: Self::Mut, f: F, ) -> Option> { diff --git a/packages/signals/src/global/memo.rs b/packages/signals/src/global/memo.rs index d48d4ffa5..6ab7c3738 100644 --- a/packages/signals/src/global/memo.rs +++ b/packages/signals/src/global/memo.rs @@ -51,14 +51,18 @@ impl GlobalMemo { } } -impl Readable for GlobalMemo { +impl Readable for GlobalMemo { + type Target = T; type Ref = generational_box::GenerationalRef>; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { ::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { diff --git a/packages/signals/src/global/signal.rs b/packages/signals/src/global/signal.rs index 96db09cca..99ef1d5e6 100644 --- a/packages/signals/src/global/signal.rs +++ b/packages/signals/src/global/signal.rs @@ -65,7 +65,8 @@ impl GlobalSignal { &self, f: impl Fn(&T) -> &O + 'static, ) -> MappedSignal>> { - MappedSignal::new(self.signal(), f) + // MappedSignal::new(self.signal(), f) + todo!() } /// Get the generational id of the signal. @@ -74,14 +75,18 @@ impl GlobalSignal { } } -impl Readable for GlobalSignal { +impl Readable for GlobalSignal { + type Target = T; type Ref = generational_box::GenerationalRef>; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { ::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { @@ -99,17 +104,21 @@ impl Readable for GlobalSignal { } } -impl Writable for GlobalSignal { +impl Writable for GlobalSignal { type Mut = Write; - fn map_mut &mut U>( + fn map_mut &mut U>( ref_: Self::Mut, f: F, ) -> Self::Mut { Write::map(ref_, f) } - fn try_map_mut Option<&mut U>>( + fn try_map_mut< + I: ?Sized + 'static, + U: ?Sized + 'static, + F: FnOnce(&mut I) -> Option<&mut U>, + >( ref_: Self::Mut, f: F, ) -> Option> { @@ -151,7 +160,7 @@ impl Deref for GlobalSignal { // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. let uninit_closure = move || { - as Readable>::read(unsafe { &*uninit_callable.as_ptr() }).clone() + as Readable>::read(unsafe { &*uninit_callable.as_ptr() }).clone() }; // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. diff --git a/packages/signals/src/map.rs b/packages/signals/src/map.rs index 640ca9604..b23d82ef8 100644 --- a/packages/signals/src/map.rs +++ b/packages/signals/src/map.rs @@ -3,112 +3,105 @@ use crate::CopyValue; use crate::Signal; use crate::SignalData; use dioxus_core::ScopeId; +use generational_box::AnyStorage; use generational_box::Storage; +use generational_box::UnsyncStorage; use std::fmt::Debug; use std::fmt::Display; /// A read only signal that has been mapped to a new type. -pub struct MappedSignal { - origin_scope: ScopeId, - mapping: CopyValue U>>, +pub struct MappedSignal { + mapping: CopyValue S::Ref>>, } impl MappedSignal<()> { /// Create a new mapped signal. - pub fn new( - signal: Signal, - mapping: impl Fn(&T) -> &U + 'static, - ) -> MappedSignal> + pub fn new(readable: R, mapping: impl Fn(&T) -> &U + 'static) -> MappedSignal where S: Storage>, U: ?Sized, { - MappedSignal { - origin_scope: signal.origin_scope(), - mapping: CopyValue::new(Box::new(move || S::map(signal.read(), &mapping))), - } + todo!() + // MappedSignal { + // mapping: CopyValue::new(Box::new(move || S::map(signal.read(), &mapping))), + // } } } -impl MappedSignal { - /// Get the scope that the signal was created in. - pub fn origin_scope(&self) -> ScopeId { - self.origin_scope - } +// impl MappedSignal { +// /// Get the current value of the signal. This will subscribe the current scope to the signal. +// pub fn read(&self) -> U { +// (self.mapping.read())() +// } - /// Get the current value of the signal. This will subscribe the current scope to the signal. - pub fn read(&self) -> U { - (self.mapping.read())() - } +// /// Run a closure with a reference to the signal's value. +// pub fn with(&self, f: impl FnOnce(U) -> O) -> O { +// f(self.read()) +// } +// } - /// Run a closure with a reference to the signal's value. - pub fn with(&self, f: impl FnOnce(U) -> O) -> O { - f(self.read()) - } -} +// impl MappedSignal { +// /// Get the current value of the signal. This will subscribe the current scope to the signal. +// pub fn value(&self) -> U { +// self.read().clone() +// } +// } -impl MappedSignal { - /// Get the current value of the signal. This will subscribe the current scope to the signal. - pub fn value(&self) -> U { - self.read().clone() - } -} +// impl PartialEq for MappedSignal { +// fn eq(&self, other: &Self) -> bool { +// self.mapping == other.mapping +// } +// } -impl PartialEq for MappedSignal { - fn eq(&self, other: &Self) -> bool { - self.mapping == other.mapping - } -} +// impl std::clone::Clone for MappedSignal { +// fn clone(&self) -> Self { +// *self +// } +// } -impl std::clone::Clone for MappedSignal { - fn clone(&self) -> Self { - *self - } -} +// impl Copy for MappedSignal {} -impl Copy for MappedSignal {} +// impl Display for MappedSignal { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// self.with(|v| Display::fmt(&v, f)) +// } +// } -impl Display for MappedSignal { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.with(|v| Display::fmt(&v, f)) - } -} +// impl Debug for MappedSignal { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// self.with(|v| Debug::fmt(&v, f)) +// } +// } -impl Debug for MappedSignal { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.with(|v| Debug::fmt(&v, f)) - } -} +// impl std::ops::Deref for MappedSignal { +// type Target = dyn Fn() -> T; -impl std::ops::Deref for MappedSignal { - type Target = dyn Fn() -> T; +// fn deref(&self) -> &Self::Target { +// // https://github.com/dtolnay/case-studies/tree/master/callable-types - fn deref(&self) -> &Self::Target { - // https://github.com/dtolnay/case-studies/tree/master/callable-types +// // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit). +// let uninit_callable = std::mem::MaybeUninit::::uninit(); +// // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. +// let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }); - // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit). - let uninit_callable = std::mem::MaybeUninit::::uninit(); - // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. - let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }); +// // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. +// let size_of_closure = std::mem::size_of_val(&uninit_closure); +// assert_eq!(size_of_closure, std::mem::size_of::()); - // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. - let size_of_closure = std::mem::size_of_val(&uninit_closure); - assert_eq!(size_of_closure, std::mem::size_of::()); +// // Then cast the lifetime of the closure to the lifetime of &self. +// fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T { +// b +// } +// let reference_to_closure = cast_lifetime( +// { +// // The real closure that we will never use. +// &uninit_closure +// }, +// // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self. +// unsafe { std::mem::transmute(self) }, +// ); - // Then cast the lifetime of the closure to the lifetime of &self. - fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T { - b - } - let reference_to_closure = cast_lifetime( - { - // The real closure that we will never use. - &uninit_closure - }, - // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self. - unsafe { std::mem::transmute(self) }, - ); - - // Cast the closure to a trait object. - reference_to_closure as &Self::Target - } -} +// // Cast the closure to a trait object. +// reference_to_closure as &Self::Target +// } +// } diff --git a/packages/signals/src/read.rs b/packages/signals/src/read.rs index 14bf14580..c54095769 100644 --- a/packages/signals/src/read.rs +++ b/packages/signals/src/read.rs @@ -1,66 +1,73 @@ -use std::{mem::MaybeUninit, ops::Deref}; +use std::{ + mem::MaybeUninit, + ops::{Deref, Index}, +}; /// A trait for states that can be read from like [`crate::Signal`], [`crate::GlobalSignal`], or [`crate::ReadOnlySignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Readable`] type. -pub trait Readable { +pub trait Readable { + /// The target type of the reference. + type Target: ?Sized + 'static; + /// The type of the reference. type Ref: Deref; /// Map the reference to a new type. - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref; + fn map_ref &U>(ref_: Self::Ref, f: F) + -> Self::Ref; /// Try to map the reference to a new type. - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option>; /// Try to get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. - fn try_read(&self) -> Result, generational_box::BorrowError>; + fn try_read(&self) -> Result, generational_box::BorrowError>; /// Get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. #[track_caller] - fn read(&self) -> Self::Ref { + fn read(&self) -> Self::Ref { self.try_read().unwrap() } /// Get the current value of the state without subscribing to updates. If the value has been dropped, this will panic. - fn peek(&self) -> Self::Ref; + fn peek(&self) -> Self::Ref; /// Clone the inner value and return it. If the value has been dropped, this will panic. #[track_caller] - fn cloned(&self) -> T + fn cloned(&self) -> Self::Target where - T: Clone, + Self::Target: Clone, { self.read().clone() } /// Run a function with a reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn with(&self, f: impl FnOnce(&T) -> O) -> O { + fn with(&self, f: impl FnOnce(&Self::Target) -> O) -> O { f(&*self.read()) } /// Run a function with a reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn with_peek(&self, f: impl FnOnce(&T) -> O) -> O { + fn with_peek(&self, f: impl FnOnce(&Self::Target) -> O) -> O { f(&*self.peek()) } /// Index into the inner value and return a reference to the result. If the value has been dropped or the index is invalid, this will panic. #[track_caller] - fn index(&self, index: I) -> Self::Ref + fn index(&self, index: I) -> Self::Ref<>::Output> where - T: std::ops::Index, + Self::Target: std::ops::Index, { Self::map_ref(self.read(), |v| v.index(index)) } #[doc(hidden)] - fn deref_impl<'a>(&self) -> &'a dyn Fn() -> T + fn deref_impl<'a>(&self) -> &'a dyn Fn() -> Self::Target where Self: Sized + 'a, - T: Clone, + Self::Target: Clone, { // https://github.com/dtolnay/case-studies/tree/master/callable-types @@ -92,7 +99,7 @@ pub trait Readable { } /// An extension trait for Readable> that provides some convenience methods. -pub trait ReadableVecExt: Readable> { +pub trait ReadableVecExt: Readable> { /// Returns the length of the inner vector. #[track_caller] fn len(&self) -> usize { @@ -144,7 +151,7 @@ pub struct ReadableValueIterator<'a, T, R> { phantom: std::marker::PhantomData, } -impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, T, R> { +impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, T, R> { type Item = R::Ref; fn next(&mut self) -> Option { @@ -157,12 +164,12 @@ impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, impl ReadableVecExt for R where T: 'static, - R: Readable>, + R: Readable>, { } /// An extension trait for Readable> that provides some convenience methods. -pub trait ReadableOptionExt: Readable> { +pub trait ReadableOptionExt: Readable> { /// Unwraps the inner value and clones it. #[track_caller] fn unwrap(&self) -> T @@ -182,6 +189,6 @@ pub trait ReadableOptionExt: Readable> { impl ReadableOptionExt for R where T: 'static, - R: Readable>, + R: Readable>, { } diff --git a/packages/signals/src/read_only_signal.rs b/packages/signals/src/read_only_signal.rs index 8b75d095b..e4ba84945 100644 --- a/packages/signals/src/read_only_signal.rs +++ b/packages/signals/src/read_only_signal.rs @@ -54,14 +54,18 @@ impl>> ReadOnlySignal { } } -impl>> Readable for ReadOnlySignal { +impl>> Readable for ReadOnlySignal { + type Target = T; type Ref = S::Ref; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { S::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index a35360695..36ebefa91 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -189,7 +189,8 @@ impl>> Signal { /// Map the signal to a new type. pub fn map(self, f: impl Fn(&T) -> &O + 'static) -> MappedSignal> { - MappedSignal::new(self, f) + // MappedSignal::new(self, f) + todo!() } /// Get the generational id of the signal. @@ -198,14 +199,18 @@ impl>> Signal { } } -impl>> Readable for Signal { +impl>> Readable for Signal { + type Target = T; type Ref = S::Ref; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { S::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { @@ -231,17 +236,21 @@ impl>> Readable for Signal { } } -impl>> Writable for Signal { +impl>> Writable for Signal { type Mut = Write; - fn map_mut &mut U>( + fn map_mut &mut U>( ref_: Self::Mut, f: F, ) -> Self::Mut { Write::map(ref_, f) } - fn try_map_mut Option<&mut U>>( + fn try_map_mut< + I: ?Sized + 'static, + U: ?Sized + 'static, + F: FnOnce(&mut I) -> Option<&mut U>, + >( ref_: Self::Mut, f: F, ) -> Option> { diff --git a/packages/signals/src/write.rs b/packages/signals/src/write.rs index 02ab44c82..8866eac96 100644 --- a/packages/signals/src/write.rs +++ b/packages/signals/src/write.rs @@ -1,40 +1,46 @@ use std::ops::DerefMut; +use std::ops::IndexMut; use crate::read::Readable; /// A trait for states that can be read from like [`crate::Signal`], or [`crate::GlobalSignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Writable`] type. -pub trait Writable: Readable { +pub trait Writable: Readable { /// The type of the reference. type Mut: DerefMut; /// Map the reference to a new type. - fn map_mut &mut U>(ref_: Self::Mut, f: F) - -> Self::Mut; + fn map_mut &mut U>( + ref_: Self::Mut, + f: F, + ) -> Self::Mut; /// Try to map the reference to a new type. - fn try_map_mut Option<&mut U>>( + fn try_map_mut Option<&mut U>>( ref_: Self::Mut, f: F, ) -> Option>; /// Get a mutable reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn write(&mut self) -> Self::Mut { + fn write(&mut self) -> Self::Mut { self.try_write().unwrap() } /// Try to get a mutable reference to the value. If the value has been dropped, this will panic. - fn try_write(&self) -> Result, generational_box::BorrowMutError>; + fn try_write(&self) -> Result, generational_box::BorrowMutError>; /// Run a function with a mutable reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn with_mut(&mut self, f: impl FnOnce(&mut T) -> O) -> O { + fn with_mut(&mut self, f: impl FnOnce(&mut Self::Target) -> O) -> O { f(&mut *self.write()) } /// Set the value of the signal. This will trigger an update on all subscribers. #[track_caller] - fn set(&mut self, value: T) { + fn set(&mut self, value: Self::Target) + where + Self::Target: Sized, + { *self.write() = value; } @@ -42,38 +48,41 @@ pub trait Writable: Readable { #[track_caller] fn toggle(&mut self) where - T: std::ops::Not + Clone, + Self::Target: std::ops::Not + Clone, { self.set(!self.cloned()); } /// Index into the inner value and return a reference to the result. #[track_caller] - fn index_mut(&mut self, index: I) -> Self::Mut + fn index_mut(&mut self, index: I) -> Self::Mut<>::Output> where - T: std::ops::IndexMut, + Self::Target: std::ops::IndexMut, { Self::map_mut(self.write(), |v| v.index_mut(index)) } /// Takes the value out of the Signal, leaving a Default in its place. #[track_caller] - fn take(&mut self) -> T + fn take(&mut self) -> Self::Target where - T: Default, + Self::Target: Default, { self.with_mut(|v| std::mem::take(v)) } /// Replace the value in the Signal, returning the old value. #[track_caller] - fn replace(&mut self, value: T) -> T { + fn replace(&mut self, value: Self::Target) -> Self::Target + where + Self::Target: Sized, + { self.with_mut(|v| std::mem::replace(v, value)) } } /// An extension trait for Writable> that provides some convenience methods. -pub trait WritableOptionExt: Writable> { +pub trait WritableOptionExt: Writable> { /// Gets the value out of the Option, or inserts the given value if the Option is empty. fn get_or_insert(&mut self, default: T) -> Self::Mut { self.get_or_insert_with(|| default) @@ -101,12 +110,12 @@ pub trait WritableOptionExt: Writable> { impl WritableOptionExt for W where T: 'static, - W: Writable>, + W: Writable>, { } /// An extension trait for Writable> that provides some convenience methods. -pub trait WritableVecExt: Writable> { +pub trait WritableVecExt: Writable> { /// Pushes a new value to the end of the vector. #[track_caller] fn push(&mut self, value: T) { @@ -194,7 +203,7 @@ pub struct WritableValueIterator { phantom: std::marker::PhantomData, } -impl>> Iterator for WritableValueIterator { +impl>> Iterator for WritableValueIterator { type Item = R::Mut; fn next(&mut self) -> Option { @@ -207,6 +216,6 @@ impl>> Iterator for WritableValueIterator { impl WritableVecExt for W where T: 'static, - W: Writable>, + W: Writable>, { }