| -rw-r--r-- | src/error.rs | 8 | ||||
| -rw-r--r-- | src/impls/core/reference.rs | 180 | ||||
| -rw-r--r-- | src/impls/core/str.rs | 60 | ||||
| -rw-r--r-- | src/transform.rs | 16 | ||||
| -rw-r--r-- | src/walk.rs | 17 | ||||
| -rw-r--r-- | tests/demo.rs | 18 |
6 files changed, 227 insertions, 72 deletions
diff --git a/src/error.rs b/src/error.rs index d975312..2e30c9f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,6 +9,14 @@ pub trait VisitorError<'value, 'ctx: 'value> { fn wrong_hint<P: Protocol<'value, 'ctx>>() -> Self; } +pub struct A<'value>(&'value str); + +impl<'value, 'ctx: 'value> VisitorError<'value, 'ctx> for A<'value> { + fn wrong_hint<P: Protocol<'value, 'ctx>>() -> Self { + todo!() + } +} + #[derive(thiserror::Error, Debug)] pub enum UniError<WalkerErr, VisitorErr> { #[error(transparent)] diff --git a/src/impls/core/reference.rs b/src/impls/core/reference.rs index 457af7a..d1fe29e 100644 --- a/src/impls/core/reference.rs +++ b/src/impls/core/reference.rs @@ -21,40 +21,77 @@ use crate::{ walk::{Walk, WalkMut, WalkOnce}, }; -impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> WalkOnce<'value, 'ctx, VisitorErr> - for &'ctx T -where - T: Walk<'value, 'ctx, VisitorErr>, -{ - type ErrorOnce = T::Error; - type WalkerOnce = T::Walker; - - fn into_walker(self) -> T::Walker { - T::walker(self) - } -} - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> WalkMut<'value, 'ctx, VisitorErr> - for &'ctx T -where - T: Walk<'value, 'ctx, VisitorErr>, -{ - type ErrorMut = T::Error; - type WalkerMut = T::Walker; - - fn walker_mut(&'value mut self) -> T::Walker { - T::walker(*self) - } -} - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> Walk<'value, 'ctx, VisitorErr> for &'ctx T +// impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> WalkOnce<'value, 'ctx, VisitorErr> +// for &'ctx T +// where +// T: Walk<'value, 'ctx, VisitorErr>, +// { +// type ErrorOnce = T::Error; +// type WalkerOnce = T::Walker; +// +// fn into_walker(self) -> T::Walker { +// T::walker(self) +// } +// } +// +// impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T: ?Sized> WalkMut<'value, 'ctx, VisitorErr> +// for &'ctx T +// where +// T: Walk<'value, 'ctx, VisitorErr>, +// { +// type ErrorMut = T::Error; +// type WalkerMut = T::Walker; +// +// fn walker_mut(&'value mut self) -> T::Walker { +// T::walker(*self) +// } +// } + +// pub struct Error<'value, 'ctx, E>(E, PhantomData<&'value &'ctx ()>); +// +// impl<'value, 'ctx, E: WalkerError<'ctx, 'static>> WalkerError<'value, 'ctx> for Error<'value, 'ctx, E> { +// fn wrong_visit<P: crate::protocol::Protocol<'value, 'ctx>>() -> Self { +// todo!() +// } +// +// fn needs_hint() -> Self { +// todo!() +// } +// } +// +// pub struct Walker<'value, 'ctx, 'root, W>(W, PhantomData<&'value &'ctx &'root ()>); +// +// impl<'value, 'ctx: 'value, 'root: 'ctx, W: crate::Walker<'value, 'ctx, VisitorErr>, VisitorErr> crate::Walker<'value, 'ctx, VisitorErr> for Walker<'value, 'ctx, 'root, W> +// { +// type Error = Error<'value, 'ctx, 'root, W::Error>; +// +// fn walk( +// &mut self, +// visitor: &mut dyn crate::Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>, +// ) -> Result<crate::WalkStatus, UniError<Self::Error, VisitorErr>> { +// todo!() +// } +// +// fn all_protocols() -> impl Iterator<Item = crate::protocol::ProtocolDescription> +// where +// Self: Sized { +// W::all_protocols() +// } +// } + +/// `'value` and `'ctx` form the bounds of the possible lifetimes. +/// These are what the walker will actually work with. +/// +/// `'value`` < `'borrow` < `'ctx` +/// `'borrow` allows &'value &'borrow T to forward to T's &'borrow T +impl<'value, 'method: 'value, 'borrow: 'method, 'ctx: 'borrow, VisitorErr, T: ?Sized> Walk<'value, 'method, 'ctx, VisitorErr> for &'borrow T where - T: Walk<'value, 'ctx, VisitorErr>, + T: Walk<'value, 'borrow, 'ctx, VisitorErr>, { type Error = T::Error; type Walker = T::Walker; - fn walker(&'value self) -> Self::Walker { + fn walker(&'method self) -> Self::Walker { T::walker(self) } } @@ -172,6 +209,91 @@ impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> } } +#[derive(Debug)] +pub struct BuilderRefContext<'ctx, T: ?Sized>(Option<&'ctx T>); + +impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> Builder<'value, 'ctx, WalkerErr> + for BuilderRefContext<'ctx, T> +{ + type Error = Missing<WrongProtocol<ShortLifetime>>; + + type Value = &'ctx T; + + fn init() -> Self + where + Self: Sized, + { + Self(None) + } + + fn as_visitor( + &mut self, + ) -> &mut dyn crate::Visitor<'value, 'ctx, WalkerErr, Error = Self::Error> { + self + } + + fn finish(self) -> Result<Self::Value, crate::error::UniError<WalkerErr, Self::Error>> + where + Self: Sized, + { + self.0.ok_or(UniError::Visitor(Missing::Missing)) + } +} + +impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> + crate::Visitor<'value, 'ctx, WalkerErr> for BuilderRefContext<'ctx, T> +{ + type Error = Missing<WrongProtocol<ShortLifetime>>; + + fn protocol( + &mut self, + id: crate::protocol::ProtocolId, + ) -> Option<crate::protocol::AnyVisit<'_, 'value, 'ctx, WalkerErr, Self::Error>> { + match id { + id if id == ProtocolId::of::<Reference<T>>() => Some(AnyVisit::new(self)), + _ => None, + } + } + + fn all_protocols() -> impl Iterator<Item = crate::protocol::ProtocolDescription> + where + Self: Sized, + { + protocol_list![Reference<T>] + } +} + +impl<'value, 'ctx: 'value, WalkerErr: 'value, T: ?Sized + Any> + Visit<'value, 'ctx, Reference<T>, WalkerErr> for BuilderRefContext<'ctx, T> +{ + type Error = Missing<WrongProtocol<ShortLifetime>>; + + fn visit<'walking>( + &'walking mut self, + accessor: <Reference<T> as crate::protocol::Protocol<'value, 'ctx>>::Accessor< + 'walking, + WalkerErr, + Self::Error, + >, + ) -> Result<(), UniError<WalkerErr, Self::Error>> { + use reference::Ref::*; + + match accessor { + Walking(_) => Err(UniError::Visitor(Missing::Error(WrongProtocol::Error( + ShortLifetime::Walking, + )))), + Value(_) => Err(UniError::Visitor(Missing::Error(WrongProtocol::Error( + ShortLifetime::Value, + )))), + Context(value) | Static(value) => { + self.0 = Some(value); + + Ok(()) + } + } + } +} + // === &mut T === impl<'value, 'ctx: 'value, VisitorErr: 'ctx, T> WalkOnce<'value, 'ctx, VisitorErr> for &'ctx mut T diff --git a/src/impls/core/str.rs b/src/impls/core/str.rs index a3fcc01..77ef5cc 100644 --- a/src/impls/core/str.rs +++ b/src/impls/core/str.rs @@ -15,10 +15,10 @@ use crate::{ use super::reference::BuilderRefValue; -pub struct Walker<'value, 'ctx: 'value>(&'value str, PhantomData<&'ctx ()>); +pub struct Walker<'value>(&'value str); -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> crate::Walker<'value, 'ctx, VisitorErr> - for Walker<'value, 'ctx> +impl<'value, 'borrow: 'value, 'ctx: 'borrow, VisitorErr: 'value> crate::Walker<'value, 'ctx, VisitorErr> + for Walker<'borrow> { type Error = BasicError; @@ -45,8 +45,8 @@ impl<'value, 'ctx: 'value, VisitorErr: 'ctx> crate::Walker<'value, 'ctx, Visitor } } -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkerHints<'value, 'ctx, VisitorErr> - for Walker<'value, 'ctx> +impl<'value, 'borrow: 'value, 'ctx: 'borrow, VisitorErr: 'value> WalkerHints<'value, 'ctx, VisitorErr> + for Walker<'borrow> { type Error = BasicError; @@ -61,8 +61,8 @@ impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkerHints<'value, 'ctx, VisitorEr } } -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Hint<'value, 'ctx, Reference<str>, VisitorErr> - for Walker<'value, 'ctx> +impl<'value, 'borrow: 'value, 'ctx: 'borrow, VisitorErr: 'value> Hint<'value, 'ctx, Reference<str>, VisitorErr> + for Walker<'borrow> { type Error = BasicError; @@ -93,20 +93,40 @@ impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Hint<'value, 'ctx, Reference<str>, } } -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkMut<'value, 'ctx, VisitorErr> for str { - type ErrorMut = BasicError; - type WalkerMut = Walker<'value, 'ctx>; - - fn walker_mut(&'value mut self) -> Self::WalkerMut { - Walker(self, PhantomData) - } -} - -impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Walk<'value, 'ctx, VisitorErr> for str { +// impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkMut<'value, 'ctx, VisitorErr> for str { +// type ErrorMut = BasicError; +// type WalkerMut = Walker<'value, 'ctx>; +// +// fn walker_mut(&'value mut self) -> Self::WalkerMut { +// Walker(self, PhantomData) +// } +// } + +// impl<'value, 'borrow: 'value, 'ctx: 'borrow, VisitorErr: 'value> Walk<'value, 'borrow, 'ctx, VisitorErr> for str { +// type Error = BasicError; +// type Walker = Walker<'borrow>; +// +// fn walker(&'borrow self) -> Self::Walker { +// Walker(self) +// } +// } + +impl<'value, 'borrow: 'value, 'ctx: 'borrow, VisitorErr: 'value> Walk<'value, 'borrow, 'ctx, VisitorErr> for str { type Error = BasicError; - type Walker = Walker<'value, 'ctx>; + type Walker = Walker<'borrow>; - fn walker(&'value self) -> Self::Walker { - Walker(self, PhantomData) + fn walker(&'borrow self) -> Self::Walker { + Walker(self) } } + +// +// impl<'value, 'ctx: 'value, VisitorErr: 'value> Walk<'value, 'value, 'ctx, VisitorErr> for i32 { +// type Error = BasicError; +// type Walker = Walker<'value, 'ctx>; +// +// fn walker(&'value self) -> Self::Walker { +// // Walker(self, PhantomData) +// todo!() +// } +// } diff --git a/src/transform.rs b/src/transform.rs index 12f7576..cd46681 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -29,12 +29,12 @@ where build_from_mut::<U::Builder, _, _>(value) } -pub fn from_ref<'value, 'ctx: 'value, U, T, VisitorErr>( +pub fn from_ref<'value, 'ctx: 'value, U, T: ?Sized, VisitorErr>( value: &'value T, -) -> Result<U, UniError<<T as Walk<'value, 'ctx, VisitorErr>>::Error, VisitorErr>> +) -> Result<U, UniError<<T as Walk<'value, 'value, 'ctx, VisitorErr>>::Error, VisitorErr>> where - U: Build<'value, 'ctx, <T as Walk<'value, 'ctx, VisitorErr>>::Error, Error = VisitorErr>, - T: Walk<'value, 'ctx, VisitorErr>, + U: Build<'value, 'ctx, <T as Walk<'value, 'value, 'ctx, VisitorErr>>::Error, Error = VisitorErr>, + T: Walk<'value, 'value, 'ctx, VisitorErr>, { build_from_ref::<U::Builder, _, _>(value) } @@ -73,12 +73,12 @@ where builder.finish() } -pub fn build_from_ref<'value, 'ctx: 'value, B, T, VisitorErr>( +pub fn build_from_ref<'value, 'ctx: 'value, B, T: ?Sized, VisitorErr>( value: &'value T, -) -> Result<B::Value, UniError<<T as Walk<'value, 'ctx, VisitorErr>>::Error, VisitorErr>> +) -> Result<B::Value, UniError<<T as Walk<'value, 'value, 'ctx, VisitorErr>>::Error, VisitorErr>> where - B: Builder<'value, 'ctx, <T as Walk<'value, 'ctx, VisitorErr>>::Error, Error = VisitorErr>, - T: Walk<'value, 'ctx, VisitorErr>, + B: Builder<'value, 'ctx, <T as Walk<'value, 'value, 'ctx, VisitorErr>>::Error, Error = VisitorErr>, + T: Walk<'value, 'value, 'ctx, VisitorErr>, { let mut builder = B::init(); value.walker().walk(builder.as_visitor())?; diff --git a/src/walk.rs b/src/walk.rs index e73df28..7f8c82a 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -41,11 +41,14 @@ pub trait WalkMut<'value, 'ctx: 'value, VisitorErr> { fn walker_mut(&'value mut self) -> Self::WalkerMut; } -pub trait Walk<'value, 'ctx: 'value, VisitorErr>: WalkMut<'value, 'ctx, VisitorErr> { +/// `'borrow` is a lifetime between `'value` and `'ctx`. +/// `'borrow` is the lifetime self will be borrowed from to make the walker. +/// This allows references to raise their lifetime to `'ctx`. +pub trait Walk<'value, 'borrow: 'value, 'ctx: 'borrow, VisitorErr> /*WalkMut<'value, 'ctx, VisitorErr>*/ { type Error: WalkerError<'value, 'ctx>; type Walker: Walker<'value, 'ctx, VisitorErr, Error = Self::Error>; - fn walker(&'value self) -> Self::Walker; + fn walker(&'borrow self) -> Self::Walker; } pub fn walker_once<'value, 'ctx: 'value, VisitorErr, W: WalkOnce<'value, 'ctx, VisitorErr>>( @@ -60,8 +63,8 @@ pub fn walker_mut<'value, 'ctx: 'value, VisitorErr, W: WalkMut<'value, 'ctx, Vis value.walker_mut() } -pub fn walker<'value, 'ctx: 'value, VisitorErr, W: Walk<'value, 'ctx, VisitorErr>>( - value: &'value W, -) -> W::Walker { - value.walker() -} +// pub fn walker<'value, 'ctx: 'value, 'root: 'ctx, VisitorErr, W: Walk<'value, 'ctx, 'root, VisitorErr>>( +// value: &'value W, +// ) -> W::Walker { +// value.walker() +// } diff --git a/tests/demo.rs b/tests/demo.rs index 86c022d..27a3782 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -1,18 +1,20 @@ -use uniserde::{impls::core::reference::BuilderRefValue, transform::build_from}; +use uniserde::{impls::core::reference::{BuilderRefValue, BuilderRefContext}, transform::build_from_ref}; #[test] fn demo() { let x = String::from("a"); - let y: &str = build_from::<BuilderRefValue<str>, _, _>(&*x).unwrap(); + // let y: &str = build_from_ref::<'_, 'static, BuilderRefValue<str>, _, _>(&*x).unwrap(); + let y: &str = uniserde::transform::from_ref(&*x).unwrap(); dbg!(y); - let y: &String = uniserde::transform::from(&*x).unwrap(); - dbg!(y); + // let y: &String = uniserde::transform::from(&*x).unwrap(); + // dbg!(y); todo!(); } -#[no_mangle] -pub fn example(a: &str) -> &String { - uniserde::transform::from(a).unwrap() -} +// #[no_mangle] +// pub fn example<'a>(a: &&&&&&'a str) -> &'a str { +// // uniserde::transform::from(a).unwrap() +// build_from::<BuilderRefContext<str>, _, _>(a).unwrap() +// } |