use std::fmt;
use std::sync::Arc;
pub mod sync_kp;
pub mod prelude;
pub use sync_kp::{
ArcMutexAccess, ArcRwLockAccess, LockAccess, SyncKp, SyncKpType, RcRefCellAccess,
StdMutexAccess, StdRwLockAccess,
};
#[cfg(feature = "parking_lot")]
pub use sync_kp::{
DirectParkingLotMutexAccess, DirectParkingLotRwLockAccess, ParkingLotMutexAccess,
ParkingLotRwLockAccess,
};
#[cfg(feature = "arc-swap")]
pub use sync_kp::{ArcArcSwapAccess, ArcArcSwapOptionAccess};
pub mod async_lock;
pub mod kptrait;
pub use kptrait::{
AccessorTrait, ChainExt, CoercionTrait, HofTrait, KeyPathValueTarget, KpReadable, KpTrait,
KPWritable,
};
#[cfg(feature = "pin_project")]
pub mod pin;
#[macro_export]
macro_rules! keypath {
{ $root:ident . $field:ident } => { $root::$field() };
{ $root:ident . $field:ident . $($ty:ident . $f:ident).+ } => {
$root::$field() $(.then($ty::$f()))+
};
($root:ident . $field:ident) => { $root::$field() };
($root:ident . $field:ident . $($ty:ident . $f:ident).+) => {
$root::$field() $(.then($ty::$f()))+
};
}
#[macro_export]
macro_rules! get_or {
($kp:expr, $root:expr, $default:expr) => {
$kp.get($root).unwrap_or($default)
};
($root:expr => $($path:tt)*, $default:expr) => {
$crate::get_or!($crate::keypath!($($path)*), $root, $default)
};
}
#[macro_export]
macro_rules! get_or_else {
($kp:expr, $root:expr, $closure:expr) => {
$kp.get($root).map(|r| r.clone()).unwrap_or_else($closure)
};
($root:expr => ($($path:tt)*), $closure:expr) => {
$crate::get_or_else!($crate::keypath!($($path)*), $root, $closure)
};
}
#[macro_export]
macro_rules! zip_with_kp {
($root:expr, $closure:expr => $kp1:expr, $kp2:expr) => {
match ($kp1.get($root), $kp2.get($root)) {
(Some(__a), Some(__b)) => Some($closure((__a, __b))),
_ => None,
}
};
($root:expr, $closure:expr => $kp1:expr, $kp2:expr, $kp3:expr) => {
match ($kp1.get($root), $kp2.get($root), $kp3.get($root)) {
(Some(__a), Some(__b), Some(__c)) => Some($closure((__a, __b, __c))),
_ => None,
}
};
($root:expr, $closure:expr => $kp1:expr, $kp2:expr, $kp3:expr, $kp4:expr) => {
match (
$kp1.get($root),
$kp2.get($root),
$kp3.get($root),
$kp4.get($root),
) {
(Some(__a), Some(__b), Some(__c), Some(__d)) => Some($closure((__a, __b, __c, __d))),
_ => None,
}
};
($root:expr, $closure:expr => $kp1:expr, $kp2:expr, $kp3:expr, $kp4:expr, $kp5:expr) => {
match (
$kp1.get($root),
$kp2.get($root),
$kp3.get($root),
$kp4.get($root),
$kp5.get($root),
) {
(Some(__a), Some(__b), Some(__c), Some(__d), Some(__e)) => {
Some($closure((__a, __b, __c, __d, __e)))
}
_ => None,
}
};
($root:expr, $closure:expr => $kp1:expr, $kp2:expr, $kp3:expr, $kp4:expr, $kp5:expr, $kp6:expr) => {
match (
$kp1.get($root),
$kp2.get($root),
$kp3.get($root),
$kp4.get($root),
$kp5.get($root),
$kp6.get($root),
) {
(Some(__a), Some(__b), Some(__c), Some(__d), Some(__e), Some(__f)) => {
Some($closure((__a, __b, __c, __d, __e, __f)))
}
_ => None,
}
};
}
pub type KpValue<'a, R, V> = Kp<
R,
V,
&'a R,
V, &'a mut R,
V, for<'b> fn(&'b R) -> Option<V>,
for<'b> fn(&'b mut R) -> Option<V>,
>;
pub type KpOwned<R, V> = Kp<
R,
V,
R,
V, R,
V, fn(R) -> Option<V>,
fn(R) -> Option<V>,
>;
pub type KpRoot<R> = Kp<
R,
R,
R,
R, R,
R, fn(R) -> Option<R>,
fn(R) -> Option<R>,
>;
pub type KpVoid = Kp<(), (), (), (), (), (), fn() -> Option<()>, fn() -> Option<()>>;
pub type KpDynamic<R, V> = Kp<
R,
V,
&'static R,
&'static V,
&'static mut R,
&'static mut V,
Box<dyn for<'a> Fn(&'a R) -> Option<&'a V> + Send + Sync>,
Box<dyn for<'a> Fn(&'a mut R) -> Option<&'a mut V> + Send + Sync>,
>;
pub type KpBox<'a, R, V> = Kp<
R,
V,
&'a R,
&'a V,
&'a mut R,
&'a mut V,
Box<dyn Fn(&'a R) -> Option<&'a V> + 'a>,
Box<dyn Fn(&'a mut R) -> Option<&'a mut V> + 'a>,
>;
pub type KpArc<'a, R, V> = Kp<
R,
V,
&'a R,
&'a V,
&'a mut R,
&'a mut V,
Arc<dyn Fn(&'a R) -> Option<&'a V> + Send + Sync + 'a>,
Arc<dyn Fn(&'a mut R) -> Option<&'a mut V> + Send + Sync + 'a>,
>;
pub type KpType<'a, R, V> = Kp<
R,
V,
&'a R,
&'a V,
&'a mut R,
&'a mut V,
for<'b> fn(&'b R) -> Option<&'b V>,
for<'b> fn(&'b mut R) -> Option<&'b mut V>,
>;
pub type KpTraitType<'a, R, V> = dyn KpTrait<
R,
V,
&'a R,
&'a V,
&'a mut R,
&'a mut V,
for<'b> fn(&'b R) -> Option<&'b V>,
for<'b> fn(&'b mut R) -> Option<&'b mut V>,
>;
pub type KpOptionRefCellType<'a, R, V> = Kp<
R,
V,
&'a R,
std::cell::Ref<'a, V>,
&'a mut R,
std::cell::RefMut<'a, V>,
for<'b> fn(&'b R) -> Option<std::cell::Ref<'b, V>>,
for<'b> fn(&'b mut R) -> Option<std::cell::RefMut<'b, V>>,
>;
impl<'a, R, V> KpType<'a, R, V> {
#[inline]
pub fn to_dynamic(self) -> KpDynamic<R, V> {
self.into()
}
}
impl<'a, R, V> From<KpType<'a, R, V>> for KpDynamic<R, V> {
#[inline]
fn from(kp: KpType<'a, R, V>) -> Self {
let get_fn = kp.get;
let set_fn = kp.set;
Kp::new(
Box::new(move |t: &R| get_fn(t)),
Box::new(move |t: &mut R| set_fn(t)),
)
}
}
impl<R, V, Root, Value, MutRoot, MutValue, G, S> Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
where
Root: std::borrow::Borrow<R>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutValue: std::borrow::BorrowMut<V>,
G: Fn(Root) -> Option<Value> + Send + Sync + 'static,
S: Fn(MutRoot) -> Option<MutValue> + Send + Sync + 'static,
R: 'static,
V: 'static,
{
#[inline]
pub fn into_dynamic(self) -> KpDynamic<R, V> {
let g = self.get;
let s = self.set;
Kp::new(
Box::new(move |t: &R| unsafe {
let root: Root = std::mem::transmute_copy(&t);
match g(root) {
None => None,
Some(v) => {
let r: &V = std::borrow::Borrow::borrow(&v);
Some(std::mem::transmute::<&V, &V>(r))
}
}
}),
Box::new(move |t: &mut R| unsafe {
let root: MutRoot = std::mem::transmute_copy(&t);
match s(root) {
None => None,
Some(mut v) => {
let r: &mut V = std::borrow::BorrowMut::borrow_mut(&mut v);
Some(std::mem::transmute::<&mut V, &mut V>(r))
}
}
}),
)
}
}
pub type KpComposed<R, V> = Kp<
R,
V,
&'static R,
&'static V,
&'static mut R,
&'static mut V,
Box<dyn for<'b> Fn(&'b R) -> Option<&'b V> + Send + Sync>,
Box<dyn for<'b> Fn(&'b mut R) -> Option<&'b mut V> + Send + Sync>,
>;
impl<R, V>
Kp<
R,
V,
&'static R,
&'static V,
&'static mut R,
&'static mut V,
Box<dyn for<'b> Fn(&'b R) -> Option<&'b V> + Send + Sync>,
Box<dyn for<'b> Fn(&'b mut R) -> Option<&'b mut V> + Send + Sync>,
>
{
pub fn from_closures<G, S>(get: G, set: S) -> Self
where
G: for<'b> Fn(&'b R) -> Option<&'b V> + Send + Sync + 'static,
S: for<'b> Fn(&'b mut R) -> Option<&'b mut V> + Send + Sync + 'static,
{
Self::new(Box::new(get), Box::new(set))
}
}
pub struct AKp {
getter: Rc<dyn for<'r> Fn(&'r dyn Any) -> Option<&'r dyn Any>>,
root_type_id: TypeId,
value_type_id: TypeId,
}
impl AKp {
pub fn new<'a, R, V>(keypath: KpType<'a, R, V>) -> Self
where
R: Any + 'static,
V: Any + 'static,
{
let root_type_id = TypeId::of::<R>();
let value_type_id = TypeId::of::<V>();
let getter_fn = keypath.get;
Self {
getter: Rc::new(move |any: &dyn Any| {
if let Some(root) = any.downcast_ref::<R>() {
getter_fn(root).map(|value: &V| value as &dyn Any)
} else {
None
}
}),
root_type_id,
value_type_id,
}
}
pub fn from<'a, R, V>(keypath: KpType<'a, R, V>) -> Self
where
R: Any + 'static,
V: Any + 'static,
{
Self::new(keypath)
}
pub fn get<'r>(&self, root: &'r dyn Any) -> Option<&'r dyn Any> {
(self.getter)(root)
}
pub fn root_type_id(&self) -> TypeId {
self.root_type_id
}
pub fn value_type_id(&self) -> TypeId {
self.value_type_id
}
pub fn get_as<'a, Root: Any, Value: Any>(&self, root: &'a Root) -> Option<Option<&'a Value>> {
if self.root_type_id == TypeId::of::<Root>() && self.value_type_id == TypeId::of::<Value>()
{
Some(
self.get(root as &dyn Any)
.and_then(|any| any.downcast_ref::<Value>()),
)
} else {
None
}
}
pub fn kind_name(&self) -> String {
format!("{:?}", self.value_type_id)
}
pub fn root_kind_name(&self) -> String {
format!("{:?}", self.root_type_id)
}
pub fn for_arc<Root>(&self) -> AKp
where
Root: Any + 'static,
{
let value_type_id = self.value_type_id;
let getter = self.getter.clone();
AKp {
getter: Rc::new(move |any: &dyn Any| {
if let Some(arc) = any.downcast_ref::<Arc<Root>>() {
getter(arc.as_ref() as &dyn Any)
} else {
None
}
}),
root_type_id: TypeId::of::<Arc<Root>>(),
value_type_id,
}
}
pub fn for_box<Root>(&self) -> AKp
where
Root: Any + 'static,
{
let value_type_id = self.value_type_id;
let getter = self.getter.clone();
AKp {
getter: Rc::new(move |any: &dyn Any| {
if let Some(boxed) = any.downcast_ref::<Box<Root>>() {
getter(boxed.as_ref() as &dyn Any)
} else {
None
}
}),
root_type_id: TypeId::of::<Box<Root>>(),
value_type_id,
}
}
pub fn for_rc<Root>(&self) -> AKp
where
Root: Any + 'static,
{
let value_type_id = self.value_type_id;
let getter = self.getter.clone();
AKp {
getter: Rc::new(move |any: &dyn Any| {
if let Some(rc) = any.downcast_ref::<Rc<Root>>() {
getter(rc.as_ref() as &dyn Any)
} else {
None
}
}),
root_type_id: TypeId::of::<Rc<Root>>(),
value_type_id,
}
}
pub fn for_option<Root>(&self) -> AKp
where
Root: Any + 'static,
{
let value_type_id = self.value_type_id;
let getter = self.getter.clone();
AKp {
getter: Rc::new(move |any: &dyn Any| {
if let Some(opt) = any.downcast_ref::<Option<Root>>() {
opt.as_ref().and_then(|root| getter(root as &dyn Any))
} else {
None
}
}),
root_type_id: TypeId::of::<Option<Root>>(),
value_type_id,
}
}
pub fn for_result<Root, E>(&self) -> AKp
where
Root: Any + 'static,
E: Any + 'static,
{
let value_type_id = self.value_type_id;
let getter = self.getter.clone();
AKp {
getter: Rc::new(move |any: &dyn Any| {
if let Some(result) = any.downcast_ref::<Result<Root, E>>() {
result
.as_ref()
.ok()
.and_then(|root| getter(root as &dyn Any))
} else {
None
}
}),
root_type_id: TypeId::of::<Result<Root, E>>(),
value_type_id,
}
}
pub fn map<Root, OrigValue, MappedValue, F>(&self, mapper: F) -> AKp
where
Root: Any + 'static,
OrigValue: Any + 'static,
MappedValue: Any + 'static,
F: Fn(&OrigValue) -> MappedValue + 'static,
{
let orig_root_type_id = self.root_type_id;
let orig_value_type_id = self.value_type_id;
let getter = self.getter.clone();
let mapped_type_id = TypeId::of::<MappedValue>();
AKp {
getter: Rc::new(move |any_root: &dyn Any| {
if any_root.type_id() == orig_root_type_id {
getter(any_root).and_then(|any_value| {
if orig_value_type_id == TypeId::of::<OrigValue>() {
any_value.downcast_ref::<OrigValue>().map(|orig_val| {
let mapped = mapper(orig_val);
Box::leak(Box::new(mapped)) as &dyn Any
})
} else {
None
}
})
} else {
None
}
}),
root_type_id: orig_root_type_id,
value_type_id: mapped_type_id,
}
}
pub fn filter<Root, Value, F>(&self, predicate: F) -> AKp
where
Root: Any + 'static,
Value: Any + 'static,
F: Fn(&Value) -> bool + 'static,
{
let orig_root_type_id = self.root_type_id;
let orig_value_type_id = self.value_type_id;
let getter = self.getter.clone();
AKp {
getter: Rc::new(move |any_root: &dyn Any| {
if any_root.type_id() == orig_root_type_id {
getter(any_root).filter(|any_value| {
if orig_value_type_id == TypeId::of::<Value>() {
any_value
.downcast_ref::<Value>()
.map(|val| predicate(val))
.unwrap_or(false)
} else {
false
}
})
} else {
None
}
}),
root_type_id: orig_root_type_id,
value_type_id: orig_value_type_id,
}
}
}
impl fmt::Debug for AKp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AKp")
.field("root_type_id", &self.root_type_id)
.field("value_type_id", &self.value_type_id)
.finish_non_exhaustive()
}
}
impl fmt::Display for AKp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"AKp(root_type_id={:?}, value_type_id={:?})",
self.root_type_id, self.value_type_id
)
}
}
pub struct PKp<Root> {
getter: Rc<dyn for<'r> Fn(&'r Root) -> Option<&'r dyn Any>>,
value_type_id: TypeId,
_phantom: std::marker::PhantomData<Root>,
}
impl<Root> PKp<Root>
where
Root: 'static,
{
pub fn new<'a, V>(keypath: KpType<'a, Root, V>) -> Self
where
V: Any + 'static,
{
let value_type_id = TypeId::of::<V>();
let getter_fn = keypath.get;
Self {
getter: Rc::new(move |root: &Root| getter_fn(root).map(|val: &V| val as &dyn Any)),
value_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn from<'a, V>(keypath: KpType<'a, Root, V>) -> Self
where
V: Any + 'static,
{
Self::new(keypath)
}
pub fn get<'r>(&self, root: &'r Root) -> Option<&'r dyn Any> {
(self.getter)(root)
}
pub fn value_type_id(&self) -> TypeId {
self.value_type_id
}
pub fn get_as<'a, Value: Any>(&self, root: &'a Root) -> Option<&'a Value> {
if self.value_type_id == TypeId::of::<Value>() {
self.get(root).and_then(|any| any.downcast_ref::<Value>())
} else {
None
}
}
pub fn kind_name(&self) -> String {
format!("{:?}", self.value_type_id)
}
pub fn for_arc(&self) -> PKp<Arc<Root>> {
let getter = self.getter.clone();
let value_type_id = self.value_type_id;
PKp {
getter: Rc::new(move |arc: &Arc<Root>| getter(arc.as_ref())),
value_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn for_box(&self) -> PKp<Box<Root>> {
let getter = self.getter.clone();
let value_type_id = self.value_type_id;
PKp {
getter: Rc::new(move |boxed: &Box<Root>| getter(boxed.as_ref())),
value_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn for_rc(&self) -> PKp<Rc<Root>> {
let getter = self.getter.clone();
let value_type_id = self.value_type_id;
PKp {
getter: Rc::new(move |rc: &Rc<Root>| getter(rc.as_ref())),
value_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn for_option(&self) -> PKp<Option<Root>> {
let getter = self.getter.clone();
let value_type_id = self.value_type_id;
PKp {
getter: Rc::new(move |opt: &Option<Root>| opt.as_ref().and_then(|root| getter(root))),
value_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn for_result<E>(&self) -> PKp<Result<Root, E>>
where
E: 'static,
{
let getter = self.getter.clone();
let value_type_id = self.value_type_id;
PKp {
getter: Rc::new(move |result: &Result<Root, E>| {
result.as_ref().ok().and_then(|root| getter(root))
}),
value_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn map<OrigValue, MappedValue, F>(&self, mapper: F) -> PKp<Root>
where
OrigValue: Any + 'static,
MappedValue: Any + 'static,
F: Fn(&OrigValue) -> MappedValue + 'static,
{
let orig_type_id = self.value_type_id;
let getter = self.getter.clone();
let mapped_type_id = TypeId::of::<MappedValue>();
PKp {
getter: Rc::new(move |root: &Root| {
getter(root).and_then(|any_value| {
if orig_type_id == TypeId::of::<OrigValue>() {
any_value.downcast_ref::<OrigValue>().map(|orig_val| {
let mapped = mapper(orig_val);
Box::leak(Box::new(mapped)) as &dyn Any
})
} else {
None
}
})
}),
value_type_id: mapped_type_id,
_phantom: std::marker::PhantomData,
}
}
pub fn filter<Value, F>(&self, predicate: F) -> PKp<Root>
where
Value: Any + 'static,
F: Fn(&Value) -> bool + 'static,
{
let orig_type_id = self.value_type_id;
let getter = self.getter.clone();
PKp {
getter: Rc::new(move |root: &Root| {
getter(root).filter(|any_value| {
if orig_type_id == TypeId::of::<Value>() {
any_value
.downcast_ref::<Value>()
.map(|val| predicate(val))
.unwrap_or(false)
} else {
false
}
})
}),
value_type_id: orig_type_id,
_phantom: std::marker::PhantomData,
}
}
}
impl<Root> fmt::Debug for PKp<Root> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PKp")
.field("root_ty", &std::any::type_name::<Root>())
.field("value_type_id", &self.value_type_id)
.finish_non_exhaustive()
}
}
impl<Root> fmt::Display for PKp<Root> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"PKp<{}, value_type_id={:?}>",
std::any::type_name::<Root>(),
self.value_type_id
)
}
}
#[derive(Clone)]
pub struct Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
where
Root: std::borrow::Borrow<R>,
MutRoot: std::borrow::BorrowMut<R>,
MutValue: std::borrow::BorrowMut<V>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
{
get: G,
set: S,
_p: std::marker::PhantomData<(R, V, Root, Value, MutRoot, MutValue)>,
}
#[inline]
pub fn constrain_get<R, V, F>(f: F) -> F
where
F: for<'b> Fn(&'b R) -> Option<&'b V>,
{
f
}
#[inline]
pub fn constrain_set<R, V, F>(f: F) -> F
where
F: for<'b> Fn(&'b mut R) -> Option<&'b mut V>,
{
f
}
impl<R, V, Root, Value, MutRoot, MutValue, G, S> Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
where
Root: std::borrow::Borrow<R>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutValue: std::borrow::BorrowMut<V>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
{
pub fn new(get: G, set: S) -> Self {
Self {
get,
set,
_p: std::marker::PhantomData,
}
}
#[inline]
pub fn get(&self, root: Root) -> Option<Value> {
(self.get)(root)
}
#[inline]
pub fn get_mut(&self, root: MutRoot) -> Option<MutValue> {
(self.set)(root)
}
#[inline]
pub fn get_ref<'a>(&self, root: &'a R) -> Option<&'a V>
where
G: for<'b> Fn(&'b R) -> Option<&'b V>,
{
(self.get)(root)
}
#[inline]
pub fn get_mut_ref<'a>(&self, root: &'a mut R) -> Option<&'a mut V>
where
S: for<'b> Fn(&'b mut R) -> Option<&'b mut V>,
{
(self.set)(root)
}
#[inline]
pub fn then<SV, G2, S2>(
self,
next: Kp<
V,
SV,
&'static V, &'static SV,
&'static mut V,
&'static mut SV,
G2,
S2,
>,
) -> Kp<
R,
SV,
&'static R,
&'static SV,
&'static mut R,
&'static mut SV,
impl for<'b> Fn(&'b R) -> Option<&'b SV>,
impl for<'b> Fn(&'b mut R) -> Option<&'b mut SV>,
>
where
G: for<'b> Fn(&'b R) -> Option<&'b V>,
S: for<'b> Fn(&'b mut R) -> Option<&'b mut V>,
G2: for<'b> Fn(&'b V) -> Option<&'b SV>,
S2: for<'b> Fn(&'b mut V) -> Option<&'b mut SV>,
{
let first_get = self.get;
let first_set = self.set;
let second_get = next.get;
let second_set = next.set;
Kp::new(
constrain_get(move |root: &R| first_get(root).and_then(|value| second_get(value))),
constrain_set(move |root: &mut R| first_set(root).and_then(|value| second_set(value))),
)
}
}
impl<R, V, Root, Value, MutRoot, MutValue, G, S> fmt::Debug
for Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
where
Root: std::borrow::Borrow<R>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutValue: std::borrow::BorrowMut<V>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Kp")
.field("root_ty", &std::any::type_name::<R>())
.field("value_ty", &std::any::type_name::<V>())
.finish_non_exhaustive()
}
}
impl<R, V, Root, Value, MutRoot, MutValue, G, S> fmt::Display
for Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
where
Root: std::borrow::Borrow<R>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutValue: std::borrow::BorrowMut<V>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Kp<{}, {}>",
std::any::type_name::<R>(),
std::any::type_name::<V>()
)
}
}
pub fn zip_kps<'a, RootType, Value1, Value2>(
kp1: &'a KpType<'a, RootType, Value1>,
kp2: &'a KpType<'a, RootType, Value2>,
) -> impl Fn(&'a RootType) -> Option<(&'a Value1, &'a Value2)> + 'a
where
RootType: 'a,
Value1: 'a,
Value2: 'a,
{
move |root: &'a RootType| {
let val1 = (kp1.get)(root)?;
let val2 = (kp2.get)(root)?;
Some((val1, val2))
}
}
impl<R, Root, MutRoot, G, S> Kp<R, R, Root, Root, MutRoot, MutRoot, G, S>
where
Root: std::borrow::Borrow<R>,
MutRoot: std::borrow::BorrowMut<R>,
G: Fn(Root) -> Option<Root>,
S: Fn(MutRoot) -> Option<MutRoot>,
{
pub fn identity_typed() -> Kp<
R,
R,
Root,
Root,
MutRoot,
MutRoot,
fn(Root) -> Option<Root>,
fn(MutRoot) -> Option<MutRoot>,
> {
Kp::new(|r: Root| Some(r), |r: MutRoot| Some(r))
}
pub fn identity<'a>() -> KpType<'a, R, R> {
KpType::new(|r| Some(r), |r| Some(r))
}
}
pub struct EnumKp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
where
Root: std::borrow::Borrow<Enum>,
Value: std::borrow::Borrow<Variant>,
MutRoot: std::borrow::BorrowMut<Enum>,
MutValue: std::borrow::BorrowMut<Variant>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
E: Fn(Variant) -> Enum,
{
extractor: Kp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S>,
embedder: E,
}
unsafe impl<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E> Send
for EnumKp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
where
Root: std::borrow::Borrow<Enum>,
Value: std::borrow::Borrow<Variant>,
MutRoot: std::borrow::BorrowMut<Enum>,
MutValue: std::borrow::BorrowMut<Variant>,
G: Fn(Root) -> Option<Value> + Send,
S: Fn(MutRoot) -> Option<MutValue> + Send,
E: Fn(Variant) -> Enum + Send,
{
}
unsafe impl<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E> Sync
for EnumKp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
where
Root: std::borrow::Borrow<Enum>,
Value: std::borrow::Borrow<Variant>,
MutRoot: std::borrow::BorrowMut<Enum>,
MutValue: std::borrow::BorrowMut<Variant>,
G: Fn(Root) -> Option<Value> + Sync,
S: Fn(MutRoot) -> Option<MutValue> + Sync,
E: Fn(Variant) -> Enum + Sync,
{
}
impl<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
EnumKp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
where
Root: std::borrow::Borrow<Enum>,
Value: std::borrow::Borrow<Variant>,
MutRoot: std::borrow::BorrowMut<Enum>,
MutValue: std::borrow::BorrowMut<Variant>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
E: Fn(Variant) -> Enum,
{
pub fn new(
extractor: Kp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S>,
embedder: E,
) -> Self {
Self {
extractor,
embedder,
}
}
pub fn get(&self, enum_value: Root) -> Option<Value> {
(self.extractor.get)(enum_value)
}
pub fn get_mut(&self, enum_value: MutRoot) -> Option<MutValue> {
(self.extractor.set)(enum_value)
}
pub fn embed(&self, value: Variant) -> Enum {
(self.embedder)(value)
}
pub fn as_kp(&self) -> &Kp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S> {
&self.extractor
}
pub fn into_kp(self) -> Kp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S> {
self.extractor
}
pub fn map<MappedValue, F>(
&self,
mapper: F,
) -> EnumKp<
Enum,
MappedValue,
Root,
MappedValue,
MutRoot,
MappedValue,
impl Fn(Root) -> Option<MappedValue>,
impl Fn(MutRoot) -> Option<MappedValue>,
impl Fn(MappedValue) -> Enum,
>
where
F: Fn(&Variant) -> MappedValue + Copy + 'static,
Variant: 'static,
MappedValue: 'static,
E: Fn(Variant) -> Enum + Copy + 'static,
{
let mapped_extractor = self.extractor.map(mapper);
let new_embedder = move |_value: MappedValue| -> Enum {
panic!(
"Cannot embed mapped values back into enum. Use the original EnumKp for embedding."
)
};
EnumKp::new(mapped_extractor, new_embedder)
}
pub fn filter<F>(
&self,
predicate: F,
) -> EnumKp<
Enum,
Variant,
Root,
Value,
MutRoot,
MutValue,
impl Fn(Root) -> Option<Value>,
impl Fn(MutRoot) -> Option<MutValue>,
E,
>
where
F: Fn(&Variant) -> bool + Copy + 'static,
Variant: 'static,
E: Copy,
{
let filtered_extractor = self.extractor.filter(predicate);
EnumKp::new(filtered_extractor, self.embedder)
}
}
impl<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E> fmt::Debug
for EnumKp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
where
Root: std::borrow::Borrow<Enum>,
Value: std::borrow::Borrow<Variant>,
MutRoot: std::borrow::BorrowMut<Enum>,
MutValue: std::borrow::BorrowMut<Variant>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
E: Fn(Variant) -> Enum,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EnumKp")
.field("enum_ty", &std::any::type_name::<Enum>())
.field("variant_ty", &std::any::type_name::<Variant>())
.finish_non_exhaustive()
}
}
impl<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E> fmt::Display
for EnumKp<Enum, Variant, Root, Value, MutRoot, MutValue, G, S, E>
where
Root: std::borrow::Borrow<Enum>,
Value: std::borrow::Borrow<Variant>,
MutRoot: std::borrow::BorrowMut<Enum>,
MutValue: std::borrow::BorrowMut<Variant>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
E: Fn(Variant) -> Enum,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"EnumKp<{}, {}>",
std::any::type_name::<Enum>(),
std::any::type_name::<Variant>()
)
}
}
pub type EnumKpType<'a, Enum, Variant> = EnumKp<
Enum,
Variant,
&'a Enum,
&'a Variant,
&'a mut Enum,
&'a mut Variant,
for<'b> fn(&'b Enum) -> Option<&'b Variant>,
for<'b> fn(&'b mut Enum) -> Option<&'b mut Variant>,
fn(Variant) -> Enum,
>;
pub fn enum_variant<'a, Enum, Variant>(
getter: for<'b> fn(&'b Enum) -> Option<&'b Variant>,
setter: for<'b> fn(&'b mut Enum) -> Option<&'b mut Variant>,
embedder: fn(Variant) -> Enum,
) -> EnumKpType<'a, Enum, Variant> {
EnumKp::new(Kp::new(getter, setter), embedder)
}
pub fn enum_ok<'a, T, E>() -> EnumKpType<'a, Result<T, E>, T> {
EnumKp::new(
Kp::new(
|r: &Result<T, E>| r.as_ref().ok(),
|r: &mut Result<T, E>| r.as_mut().ok(),
),
|t: T| Ok(t),
)
}
pub fn enum_err<'a, T, E>() -> EnumKpType<'a, Result<T, E>, E> {
EnumKp::new(
Kp::new(
|r: &Result<T, E>| r.as_ref().err(),
|r: &mut Result<T, E>| r.as_mut().err(),
),
|e: E| Err(e),
)
}
pub fn enum_some<'a, T>() -> EnumKpType<'a, Option<T>, T> {
EnumKp::new(
Kp::new(|o: &Option<T>| o.as_ref(), |o: &mut Option<T>| o.as_mut()),
|t: T| Some(t),
)
}
pub fn variant_of<'a, Enum, Variant>(
getter: for<'b> fn(&'b Enum) -> Option<&'b Variant>,
setter: for<'b> fn(&'b mut Enum) -> Option<&'b mut Variant>,
embedder: fn(Variant) -> Enum,
) -> EnumKpType<'a, Enum, Variant> {
enum_variant(getter, setter, embedder)
}
pub fn kp_box<'a, T>() -> KpType<'a, Box<T>, T> {
Kp::new(
|b: &Box<T>| Some(b.as_ref()),
|b: &mut Box<T>| Some(b.as_mut()),
)
}
pub fn kp_arc<'a, T>() -> Kp<
Arc<T>,
T,
&'a Arc<T>,
&'a T,
&'a mut Arc<T>,
&'a mut T,
for<'b> fn(&'b Arc<T>) -> Option<&'b T>,
for<'b> fn(&'b mut Arc<T>) -> Option<&'b mut T>,
> {
Kp::new(
|arc: &Arc<T>| Some(arc.as_ref()),
|arc: &mut Arc<T>| Arc::get_mut(arc),
)
}
pub fn kp_rc<'a, T>() -> Kp<
std::rc::Rc<T>,
T,
&'a std::rc::Rc<T>,
&'a T,
&'a mut std::rc::Rc<T>,
&'a mut T,
for<'b> fn(&'b std::rc::Rc<T>) -> Option<&'b T>,
for<'b> fn(&'b mut std::rc::Rc<T>) -> Option<&'b mut T>,
> {
Kp::new(
|rc: &std::rc::Rc<T>| Some(rc.as_ref()),
|rc: &mut std::rc::Rc<T>| std::rc::Rc::get_mut(rc),
)
}
use std::any::{Any, TypeId};
use std::rc::Rc;