use crate::prelude::*;
use core::ops::Deref;
#[cfg(not(feature = "std"))]
use alloc::rc::{Rc, Weak as RcWeak};
#[cfg(not(feature = "std"))]
use alloc::sync::Weak as ArcWeak;
#[cfg(feature = "std")]
use std::rc::{Rc, Weak as RcWeak};
#[cfg(feature = "std")]
use std::sync::Weak as ArcWeak;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
pub(crate) mod shared_tracking {
use core::cell::RefCell;
use rustc_hash::FxHashMap;
pub(crate) enum TrackOutcome {
NotActive,
New(u32),
Existing(u32),
}
struct AnchorState {
seen: FxHashMap<usize, u32>,
next_id: u32,
}
impl AnchorState {
fn new() -> Self {
Self {
seen: FxHashMap::default(),
next_id: 1,
}
}
}
std::thread_local! {
static STATE: RefCell<Option<AnchorState>> = const { RefCell::new(None) };
}
pub(crate) struct AnchorScope {
owns: bool,
}
impl AnchorScope {
pub(crate) fn enter() -> Self {
let owns = STATE.with(|s| {
let mut borrow = s.borrow_mut();
if borrow.is_none() {
*borrow = Some(AnchorState::new());
true
} else {
false
}
});
AnchorScope { owns }
}
}
impl Drop for AnchorScope {
fn drop(&mut self) {
if self.owns {
STATE.with(|s| {
*s.borrow_mut() = None;
});
}
}
}
pub(crate) fn track(ptr: usize) -> TrackOutcome {
STATE.with(|s| {
let mut borrow = s.borrow_mut();
match borrow.as_mut() {
None => TrackOutcome::NotActive,
Some(state) => {
if let Some(&id) = state.seen.get(&ptr) {
TrackOutcome::Existing(id)
} else {
let id = state.next_id;
state.next_id = state.next_id.saturating_add(1);
let _ = state.seen.insert(ptr, id);
TrackOutcome::New(id)
}
}
}
})
}
pub(crate) fn peek(ptr: usize) -> Option<u32> {
STATE.with(|s| {
s.borrow()
.as_ref()
.and_then(|state| state.seen.get(&ptr).copied())
})
}
pub(crate) fn format_id(id: u32) -> String {
format!("id{id:03}")
}
}
#[derive(Clone)]
pub struct RcAnchor<T>(pub Rc<T>);
impl<T: fmt::Debug> fmt::Debug for RcAnchor<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("RcAnchor").field(&self.0).finish()
}
}
impl<T> Deref for RcAnchor<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T> From<T> for RcAnchor<T> {
fn from(v: T) -> Self {
Self(Rc::new(v))
}
}
impl<T> From<Rc<T>> for RcAnchor<T> {
fn from(v: Rc<T>) -> Self {
Self(v)
}
}
impl<T> RcAnchor<T> {
pub fn into_inner(self) -> Rc<T> {
self.0
}
}
impl<T: Serialize> Serialize for RcAnchor<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[cfg(feature = "std")]
{
let ptr = Rc::as_ptr(&self.0) as *const () as usize;
match shared_tracking::track(ptr) {
shared_tracking::TrackOutcome::NotActive => self.0.serialize(serializer),
shared_tracking::TrackOutcome::New(id) => {
let id_str = shared_tracking::format_id(id);
serializer
.serialize_newtype_struct(crate::fmt::MAGIC_ANCHOR_DEF, &(id_str, &*self.0))
}
shared_tracking::TrackOutcome::Existing(id) => {
let id_str = shared_tracking::format_id(id);
serializer.serialize_newtype_struct(crate::fmt::MAGIC_ANCHOR_REF, &id_str)
}
}
}
#[cfg(not(feature = "std"))]
{
self.0.serialize(serializer)
}
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for RcAnchor<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(|v| RcAnchor(Rc::new(v)))
}
}
#[derive(Clone)]
pub struct ArcAnchor<T>(pub Arc<T>);
impl<T: fmt::Debug> fmt::Debug for ArcAnchor<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ArcAnchor").field(&self.0).finish()
}
}
impl<T> Deref for ArcAnchor<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T> From<T> for ArcAnchor<T> {
fn from(v: T) -> Self {
Self(Arc::new(v))
}
}
impl<T> From<Arc<T>> for ArcAnchor<T> {
fn from(v: Arc<T>) -> Self {
Self(v)
}
}
impl<T> ArcAnchor<T> {
pub fn into_inner(self) -> Arc<T> {
self.0
}
}
impl<T: Serialize> Serialize for ArcAnchor<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[cfg(feature = "std")]
{
let ptr = Arc::as_ptr(&self.0) as *const () as usize;
match shared_tracking::track(ptr) {
shared_tracking::TrackOutcome::NotActive => self.0.serialize(serializer),
shared_tracking::TrackOutcome::New(id) => {
let id_str = shared_tracking::format_id(id);
serializer
.serialize_newtype_struct(crate::fmt::MAGIC_ANCHOR_DEF, &(id_str, &*self.0))
}
shared_tracking::TrackOutcome::Existing(id) => {
let id_str = shared_tracking::format_id(id);
serializer.serialize_newtype_struct(crate::fmt::MAGIC_ANCHOR_REF, &id_str)
}
}
}
#[cfg(not(feature = "std"))]
{
self.0.serialize(serializer)
}
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcAnchor<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(|v| ArcAnchor(Arc::new(v)))
}
}
#[derive(Clone)]
pub struct RcWeakAnchor<T>(pub RcWeak<T>);
impl<T: fmt::Debug> fmt::Debug for RcWeakAnchor<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0.upgrade() {
Some(v) => f.debug_tuple("RcWeakAnchor").field(&v).finish(),
None => f.debug_tuple("RcWeakAnchor").field(&"(dangling)").finish(),
}
}
}
impl<T> RcWeakAnchor<T> {
pub fn dangling() -> Self {
Self(RcWeak::new())
}
pub fn into_inner(self) -> RcWeak<T> {
self.0
}
pub fn upgrade(&self) -> Option<Rc<T>> {
self.0.upgrade()
}
}
impl<T> From<RcWeak<T>> for RcWeakAnchor<T> {
fn from(v: RcWeak<T>) -> Self {
Self(v)
}
}
impl<T: Serialize> Serialize for RcWeakAnchor<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self.0.upgrade() {
Some(v) => {
#[cfg(feature = "std")]
{
let ptr = Rc::as_ptr(&v) as *const () as usize;
if let Some(id) = shared_tracking::peek(ptr) {
let id_str = shared_tracking::format_id(id);
return serializer
.serialize_newtype_struct(crate::fmt::MAGIC_ANCHOR_REF, &id_str);
}
}
v.serialize(serializer)
}
None => serializer.serialize_none(),
}
}
}
impl<'de, T> Deserialize<'de> for RcWeakAnchor<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let _ = serde::de::IgnoredAny::deserialize(deserializer)?;
Ok(RcWeakAnchor(RcWeak::new()))
}
}
#[derive(Clone)]
pub struct ArcWeakAnchor<T>(pub ArcWeak<T>);
impl<T: fmt::Debug> fmt::Debug for ArcWeakAnchor<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0.upgrade() {
Some(v) => f.debug_tuple("ArcWeakAnchor").field(&v).finish(),
None => f.debug_tuple("ArcWeakAnchor").field(&"(dangling)").finish(),
}
}
}
impl<T> ArcWeakAnchor<T> {
pub fn dangling() -> Self {
Self(ArcWeak::new())
}
pub fn into_inner(self) -> ArcWeak<T> {
self.0
}
pub fn upgrade(&self) -> Option<Arc<T>> {
self.0.upgrade()
}
}
impl<T> From<ArcWeak<T>> for ArcWeakAnchor<T> {
fn from(v: ArcWeak<T>) -> Self {
Self(v)
}
}
impl<T: Serialize> Serialize for ArcWeakAnchor<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self.0.upgrade() {
Some(v) => {
#[cfg(feature = "std")]
{
let ptr = Arc::as_ptr(&v) as *const () as usize;
if let Some(id) = shared_tracking::peek(ptr) {
let id_str = shared_tracking::format_id(id);
return serializer
.serialize_newtype_struct(crate::fmt::MAGIC_ANCHOR_REF, &id_str);
}
}
v.serialize(serializer)
}
None => serializer.serialize_none(),
}
}
}
impl<'de, T> Deserialize<'de> for ArcWeakAnchor<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let _ = serde::de::IgnoredAny::deserialize(deserializer)?;
Ok(ArcWeakAnchor(ArcWeak::new()))
}
}
pub struct AnchorRegistry<T> {
anchors: FxHashMap<String, Rc<T>>,
}
impl<T: fmt::Debug> fmt::Debug for AnchorRegistry<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AnchorRegistry")
.field("len", &self.anchors.len())
.finish()
}
}
impl<T> Default for AnchorRegistry<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> AnchorRegistry<T> {
pub fn new() -> Self {
Self {
anchors: FxHashMap::default(),
}
}
pub fn register(&mut self, name: String, value: T) -> Rc<T> {
let rc = Rc::new(value);
let _ = self.anchors.insert(name, Rc::clone(&rc));
rc
}
pub fn resolve(&self, name: &str) -> Option<Rc<T>> {
self.anchors.get(name).cloned()
}
pub fn len(&self) -> usize {
self.anchors.len()
}
pub fn is_empty(&self) -> bool {
self.anchors.is_empty()
}
pub fn clear(&mut self) {
self.anchors.clear();
}
}
pub struct ArcAnchorRegistry<T> {
anchors: FxHashMap<String, Arc<T>>,
}
impl<T: fmt::Debug> fmt::Debug for ArcAnchorRegistry<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ArcAnchorRegistry")
.field("len", &self.anchors.len())
.finish()
}
}
impl<T> Default for ArcAnchorRegistry<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> ArcAnchorRegistry<T> {
pub fn new() -> Self {
Self {
anchors: FxHashMap::default(),
}
}
pub fn register(&mut self, name: String, value: T) -> Arc<T> {
let arc = Arc::new(value);
let _ = self.anchors.insert(name, Arc::clone(&arc));
arc
}
pub fn resolve(&self, name: &str) -> Option<Arc<T>> {
self.anchors.get(name).cloned()
}
pub fn len(&self) -> usize {
self.anchors.len()
}
pub fn is_empty(&self) -> bool {
self.anchors.is_empty()
}
pub fn clear(&mut self) {
self.anchors.clear();
}
}
#[cfg(feature = "std")]
use std::cell::RefCell;
#[cfg(feature = "std")]
use std::sync::{Arc, Mutex};
#[cfg(feature = "std")]
pub struct RcRecursive<T>(pub Rc<RefCell<Option<T>>>);
#[cfg(feature = "std")]
impl<T> Clone for RcRecursive<T> {
fn clone(&self) -> Self {
RcRecursive(self.0.clone())
}
}
#[cfg(feature = "std")]
impl<T: fmt::Debug> fmt::Debug for RcRecursive<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("RcRecursive").field(&self.0).finish()
}
}
#[cfg(feature = "std")]
impl<T> Default for RcRecursive<T> {
fn default() -> Self {
Self::empty()
}
}
#[cfg(feature = "std")]
impl<T> RcRecursive<T> {
#[must_use]
pub fn empty() -> Self {
RcRecursive(Rc::new(RefCell::new(None)))
}
#[must_use]
pub fn new(value: T) -> Self {
RcRecursive(Rc::new(RefCell::new(Some(value))))
}
pub fn borrow(&self) -> core::cell::Ref<'_, Option<T>> {
self.0.borrow()
}
pub fn borrow_mut(&self) -> core::cell::RefMut<'_, Option<T>> {
self.0.borrow_mut()
}
pub fn set(&self, value: T) -> Option<T> {
self.borrow_mut().replace(value)
}
pub fn take(&self) -> Option<T> {
self.borrow_mut().take()
}
pub fn strong_count(&self) -> usize {
Rc::strong_count(&self.0)
}
pub fn downgrade(&self) -> RcRecursion<T> {
RcRecursion(Rc::downgrade(&self.0))
}
}
#[cfg(feature = "std")]
impl<T: Serialize> Serialize for RcRecursive<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match &*self.borrow() {
Some(v) => v.serialize(serializer),
None => serializer.serialize_unit(),
}
}
}
#[cfg(feature = "std")]
impl<'de, T: Deserialize<'de>> Deserialize<'de> for RcRecursive<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(RcRecursive::new)
}
}
#[cfg(feature = "std")]
pub struct RcRecursion<T>(pub RcWeak<RefCell<Option<T>>>);
#[cfg(feature = "std")]
impl<T> Clone for RcRecursion<T> {
fn clone(&self) -> Self {
RcRecursion(self.0.clone())
}
}
#[cfg(feature = "std")]
impl<T: fmt::Debug> fmt::Debug for RcRecursion<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("RcRecursion").finish()
}
}
#[cfg(feature = "std")]
impl<T> Default for RcRecursion<T> {
fn default() -> Self {
RcRecursion(RcWeak::new())
}
}
#[cfg(feature = "std")]
impl<T> RcRecursion<T> {
pub fn upgrade(&self) -> Option<RcRecursive<T>> {
self.0.upgrade().map(RcRecursive)
}
}
#[cfg(feature = "std")]
pub struct ArcRecursive<T>(pub Arc<Mutex<Option<T>>>);
#[cfg(feature = "std")]
impl<T> Clone for ArcRecursive<T> {
fn clone(&self) -> Self {
ArcRecursive(self.0.clone())
}
}
#[cfg(feature = "std")]
impl<T: fmt::Debug> fmt::Debug for ArcRecursive<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ArcRecursive").finish()
}
}
#[cfg(feature = "std")]
impl<T> Default for ArcRecursive<T> {
fn default() -> Self {
Self::empty()
}
}
#[cfg(feature = "std")]
impl<T> ArcRecursive<T> {
#[must_use]
pub fn empty() -> Self {
ArcRecursive(Arc::new(Mutex::new(None)))
}
#[must_use]
pub fn new(value: T) -> Self {
ArcRecursive(Arc::new(Mutex::new(Some(value))))
}
pub fn lock(&self) -> std::sync::MutexGuard<'_, Option<T>> {
self.0.lock().unwrap_or_else(|e| e.into_inner())
}
pub fn set(&self, value: T) -> Option<T> {
self.lock().replace(value)
}
pub fn take(&self) -> Option<T> {
self.lock().take()
}
pub fn strong_count(&self) -> usize {
Arc::strong_count(&self.0)
}
pub fn downgrade(&self) -> ArcRecursion<T> {
ArcRecursion(Arc::downgrade(&self.0))
}
}
#[cfg(feature = "std")]
impl<T: Serialize> Serialize for ArcRecursive<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match &*self.lock() {
Some(v) => v.serialize(serializer),
None => serializer.serialize_unit(),
}
}
}
#[cfg(feature = "std")]
impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcRecursive<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(ArcRecursive::new)
}
}
#[cfg(feature = "std")]
pub struct ArcRecursion<T>(pub ArcWeak<Mutex<Option<T>>>);
#[cfg(feature = "std")]
impl<T> Clone for ArcRecursion<T> {
fn clone(&self) -> Self {
ArcRecursion(self.0.clone())
}
}
#[cfg(feature = "std")]
impl<T: fmt::Debug> fmt::Debug for ArcRecursion<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ArcRecursion").finish()
}
}
#[cfg(feature = "std")]
impl<T> Default for ArcRecursion<T> {
fn default() -> Self {
ArcRecursion(ArcWeak::new())
}
}
#[cfg(feature = "std")]
impl<T> ArcRecursion<T> {
pub fn upgrade(&self) -> Option<ArcRecursive<T>> {
self.0.upgrade().map(ArcRecursive)
}
}