-rw-r--r--src/error.rs8
-rw-r--r--src/impls/core/reference.rs180
-rw-r--r--src/impls/core/str.rs60
-rw-r--r--src/transform.rs16
-rw-r--r--src/walk.rs17
-rw-r--r--tests/demo.rs18
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()
+// }