#![allow(incomplete_features)]
#![feature(const_generics)]
#![feature(arbitrary_self_types)]
#![feature(generic_associated_types)]
pub use ref_clone_derive::*;
use std::marker::PhantomData;
use std::ops::Deref;
use std::ops::DerefMut;
use std::slice::Iter;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Ref<'a, T: ?Sized, S: RefType> {
value: &'a T,
ty: PhantomData<S>,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Shared;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Unique;
pub struct RefFn<F1, F2, A, B>
where
F1: FnOnce(&A) -> &B,
F2: FnOnce(&mut A) -> &mut B,
{
pub apply: F1,
pub apply_mut: F2,
_marker: PhantomData<*const (A, B)>,
}
pub trait RefType: private::Sealed + Copy {
fn _apply_once<F1, F2, A, B>(f: RefFn<F1, F2, A, B>, x: Ref<A, Self>) -> Ref<B, Self>
where
F1: FnOnce(&A) -> &B,
F2: FnOnce(&mut A) -> &mut B;
}
pub trait IntoRef {
type Output;
fn into_ref(self) -> Self::Output;
}
pub trait RefAccessors<Wrapped> {
fn to_wrapped(self) -> Wrapped;
}
impl<F1, F2, A, B> RefFn<F1, F2, A, B>
where
F1: FnOnce(&A) -> &B,
F2: FnOnce(&mut A) -> &mut B,
{
#[inline(always)]
pub fn new(apply: F1, apply_mut: F2) -> Self {
RefFn {
apply,
apply_mut,
_marker: PhantomData,
}
}
}
impl<'a, F1, F2, A, B: 'a> RefFn<F1, F2, A, B>
where
F1: FnOnce(&A) -> &B,
F2: FnOnce(&mut A) -> &mut B,
{
#[inline(always)]
pub fn ap<T: RefType>(self, x: Ref<'a, A, T>) -> Ref<'a, B, T> {
T::_apply_once(self, x)
}
}
impl RefType for Shared {
#[inline(always)]
fn _apply_once<F1, F2, A, B>(f: RefFn<F1, F2, A, B>, x: Ref<A, Self>) -> Ref<B, Self>
where
F1: FnOnce(&A) -> &B,
F2: FnOnce(&mut A) -> &mut B,
{
Ref::new((f.apply)(x.as_ref()))
}
}
impl RefType for Unique {
#[inline(always)]
fn _apply_once<F1, F2, A, B>(f: RefFn<F1, F2, A, B>, mut x: Ref<A, Self>) -> Ref<B, Self>
where
F1: FnOnce(&A) -> &B,
F2: FnOnce(&mut A) -> &mut B,
{
Ref::new((f.apply_mut)(x.as_mut()))
}
}
impl Shared {
#[inline(always)]
pub fn new<'a, T: ?Sized>(t: &'a T) -> Ref<'a, T, Shared> {
Ref {
value: t,
ty: PhantomData,
}
}
}
impl Unique {
#[inline(always)]
pub fn new<'a, T: ?Sized>(t: &'a mut T) -> Ref<'a, T, Unique> {
Ref {
value: t,
ty: PhantomData,
}
}
}
impl<'a, T: ?Sized, S: RefType> Deref for Ref<'a, T, S> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
self.as_ref()
}
}
impl<'a, T: ?Sized> DerefMut for Ref<'a, T, Unique> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
self.as_mut()
}
}
impl<'a, T: ?Sized, S: RefType> Ref<'a, T, S> {
#[inline(always)]
pub fn as_ref(&self) -> &'a T {
self.value
}
#[inline(always)]
pub unsafe fn __new_unsafe(value: &'a T) -> Ref<'a, T, S> {
Ref {
value,
ty: PhantomData,
}
}
}
impl<'a, T: ?Sized> Ref<'a, T, Unique> {
#[inline(always)]
pub fn as_mut(&mut self) -> &'a mut T {
unsafe { (self.value as *const T as *mut T).as_mut().unwrap() }
}
}
impl<'a, T: ?Sized> IntoRef for &'a T {
type Output = Ref<'a, T, Shared>;
#[inline(always)]
fn into_ref(self) -> Self::Output {
Shared::new(self)
}
}
impl<'a, T: ?Sized> IntoRef for &'a mut T {
type Output = Ref<'a, T, Unique>;
#[inline(always)]
fn into_ref(self) -> Self::Output {
Unique::new(self)
}
}
impl<'a, T: ?Sized, S: RefType> Ref<'a, T, S> {
#[inline(always)]
pub fn new(this: impl IntoRef<Output = Self>) -> Self {
this.into_ref()
}
}
impl<'a, T: std::fmt::Debug + ?Sized, S: RefType> std::fmt::Debug for Ref<'a, T, S> {
#[inline(always)]
fn fmt(
&self,
formatter: &mut std::fmt::Formatter<'_>,
) -> std::result::Result<(), std::fmt::Error> {
self.value.fmt(formatter)
}
}
impl<'a, T: std::fmt::Display + ?Sized, S: RefType> std::fmt::Display for Ref<'a, T, S> {
#[inline(always)]
fn fmt(
&self,
formatter: &mut std::fmt::Formatter<'_>,
) -> std::result::Result<(), std::fmt::Error> {
self.value.fmt(formatter)
}
}
mod private {
use crate::*;
pub trait Sealed {}
impl Sealed for Shared {}
impl Sealed for Unique {}
impl<T, S: RefType> Sealed for Ref<'_, T, S> {}
}
mod traits;
pub use traits::*;
impl<T> IndexRef<usize> for [T] {
type Output = T;
#[inline(always)]
fn index_ref<'a, S: RefType>(self: Ref<'a, Self, S>, i: usize) -> Ref<'a, T, S> {
unsafe { Ref::__new_unsafe(&self.value[i]) }
}
}
impl<T, const N: usize> IndexRef<usize> for [T; N] {
type Output = T;
#[inline(always)]
fn index_ref<'a, S: RefType>(self: Ref<'a, Self, S>, i: usize) -> Ref<'a, T, S> {
unsafe { Ref::__new_unsafe(&self.value[i]) }
}
}
impl<T> DerefRef for Box<T> {
type Target = T;
#[inline(always)]
fn deref_ref<'a, S: RefType>(self: Ref<'a, Self, S>) -> Ref<'a, T, S> {
unsafe { Ref::__new_unsafe(self.as_ref().deref()) }
}
}
pub struct RefIter<'a, T, S: RefType> {
iter: Iter<'a, T>,
_marker: PhantomData<S>,
}
impl<'a, T, S: RefType> Iterator for RefIter<'a, T, S> {
type Item = Ref<'a, T, S>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
unsafe {
match self.iter.next() {
Some(a) => Some(Ref::__new_unsafe(a)),
None => None,
}
}
}
}
impl<'a, T: 'a> IntoIteratorRef<'a> for [T] {
type Item = T;
type IntoIter<S: RefType> = RefIter<'a, T, S>;
#[inline(always)]
fn into_iter_ref<S: RefType>(self: Ref<'a, Self, S>) -> Self::IntoIter<S> {
RefIter {
iter: self.as_ref().into_iter(),
_marker: PhantomData,
}
}
}
impl<'a, T: 'a, const N: usize> IntoIteratorRef<'a> for [T; N] {
type Item = T;
type IntoIter<S: RefType> = RefIter<'a, T, S>;
#[inline(always)]
fn into_iter_ref<S: RefType>(self: Ref<'a, Self, S>) -> Self::IntoIter<S> {
RefIter {
iter: self.as_ref().into_iter(),
_marker: PhantomData,
}
}
}