Diffstat (limited to 'src/protocol/visitor/borrow.rs')
| -rw-r--r-- | src/protocol/visitor/borrow.rs | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/protocol/visitor/borrow.rs b/src/protocol/visitor/borrow.rs new file mode 100644 index 0000000..511d429 --- /dev/null +++ b/src/protocol/visitor/borrow.rs @@ -0,0 +1,116 @@ +//! Protocol for giving a visitor a borrowed value. + +use core::marker::PhantomData; + +use crate::{builtins::walker::hint::Meta, protocol::Protocol}; + +pub struct Value<T: ?Sized>(PhantomData<fn() -> *const T>); + +pub enum Kind<'a, 'ctx: 'a, T: ?Sized> { + Temp(&'a T), + Context(&'ctx T), + TempMut(&'a mut T), + ContextMut(&'ctx mut T), +} + +impl<'a, 'ctx, T: ?Sized> Kind<'a, 'ctx, T> { + pub fn into_temp(self) -> &'a T { + use Kind as K; + match self { + K::Temp(v) | K::Context(v) => v, + K::TempMut(v) | K::ContextMut(v) => v, + } + } + + pub fn into_context(self) -> Result<&'ctx T, Self> { + use Kind as K; + match self { + K::Context(v) => Ok(v), + K::ContextMut(v) => Ok(v), + this @ (K::Temp(_) | K::TempMut(_)) => Err(this), + } + } + + pub fn into_temp_mut(self) -> Result<&'a mut T, Self> { + use Kind as K; + match self { + K::TempMut(v) | K::ContextMut(v) => Ok(v), + this @ (K::Temp(_) | K::Context(_)) => Err(this), + } + } + + pub fn into_context_mut(self) -> Result<&'ctx mut T, Self> { + use Kind as K; + match self { + K::ContextMut(v) => Ok(v), + this @ (K::Temp(_) | K::Context(_) | K::TempMut(_)) => { + Err(this) + } + } + } + + pub fn variant(&self) -> KindVariants { + use Kind as K; + use KindVariants as V; + match self { + K::Temp(_) => V::Temp, + K::Context(_) => V::Context, + K::TempMut(_) => V::TempMut, + K::ContextMut(_) => V::ContextMut, + } + } +} + +pub trait Object<'ctx, T: 'static> { + fn visit(&mut self, value: Kind<'_, 'ctx, T>) -> Result<(), ()>; +} + +impl<T: 'static> Protocol for Value<T> { + type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx, T>; +} + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub enum KindVariants { + Temp, + Context, + TempMut, + ContextMut, +} + +impl KindVariants { + pub fn can_become(&self, wanted: Self) -> bool { + use KindVariants as V; + match (self, wanted) { + (V::Temp, V::Temp) => true, + (V::Temp, V::Context) => false, + (V::Temp, V::TempMut) => false, + (V::Temp, V::ContextMut) => false, + (V::Context, V::Temp) => true, + (V::Context, V::Context) => true, + (V::Context, V::TempMut) => false, + (V::Context, V::ContextMut) => false, + (V::TempMut, V::Temp) => true, + (V::TempMut, V::Context) => false, + (V::TempMut, V::TempMut) => true, + (V::TempMut, V::ContextMut) => false, + (V::ContextMut, V::Temp) => true, + (V::ContextMut, V::Context) => true, + (V::ContextMut, V::TempMut) => true, + (V::ContextMut, V::ContextMut) => true, + } + } +} + +pub struct Known { + pub kind: Option<KindVariants>, +} + +pub struct Hint { + pub kind: Option<KindVariants>, +} + +impl<T: 'static> Meta for Value<T> { + type Known<'a, 'ctx: 'a> = Known; + + type Hint<'a, 'ctx: 'a> = Hint; +} |