daemonic_error 0.1.1

Errors that compose, predict, and leave receipts - Compose: algebraic combination (in active development) - Predict: Glass/Severity - Receipts: audit trail, position, checksum - Reflection: Runtime Reflection through TopologySegment (in active development)
//! This module exists to isolate [`RandomState`] and [`DefaultDaemonicHasher`] outside of the
//! [`collections`] module without actually publicly exporting them, so that parts of that
//! implementation can more easily be moved to the [`alloc`] crate.
//!
//! Although its items are public and contain stability attributes, they can't actually be accessed
//! outside this crate.
//!
//! [`collections`]: crate::collections
use core::cell::{Cell, UnsafeCell};
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::sync::atomic::Ordering::Release;
use core::sync::atomic::Ordering::Acquire;
use crate::{const_daemonic_hash, Severity};
use core::sync::atomic::Atomic;
use core::sync::atomic::AtomicBool;
use core::sync::atomic::Ordering::Relaxed;
#[allow(deprecated)]
use super::{BuildHasher, DaemonicHasher, DaemonicSipHasher13};
use crate::daemonic::glass::{Glass, Observation};
// use std::cell::Cell;
// use std::fs::File;
// use std::hash::random::hashmap_random_keys;
// use std::sync::atomic::{Atomic, AtomicBool};
// use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
// use std::sync::OnceLock;
use crate::daemonic::{Anchor, AnchorDomainSet, SemanticAnchor, SymbolicAnchor, TopologyAnchor, TopologySegment};
use crate::daemonic::frame::{Frame, FrameType, ReferenceFrame};
// use libc::libc::{size_t, c_void, c_uint, ssize_t};
use crate::daemonic::glass::daemonic_system_call::DaemonicSystemCall;
use crate::daemonic::topology::TOPOLOGY_ANCHOR;

//todo: Disabled until i can fix OnceLock
// fn getrandom(mut bytes: &mut [u8], insecure: bool) {
// 	static GETRANDOM_AVAILABLE: Atomic<bool> = AtomicBool::new(true);
// 	static GRND_INSECURE_AVAILABLE: Atomic<bool> = AtomicBool::new(true);
// 	static URANDOM_READY: Atomic<bool> = AtomicBool::new(false);
// 	static DEVICE: OnceLock<File> = OnceLock::new();
//
// 	if GETRANDOM_AVAILABLE.load(Relaxed) {
// 		loop {
// 			if bytes.is_empty() {
// 				return;
// 			}
//
// 			let flags = if insecure {
// 				if GRND_INSECURE_AVAILABLE.load(Relaxed) {
// 					libc::libc::GRND_INSECURE
// 				} else {
// 					libc::libc::GRND_NONBLOCK
// 				}
// 			} else {
// 				0
// 			};
//
// 			// Use DaemonicSystemCall 318 (getrandom) instead of libc wrapper
// 			let observation = DaemonicSystemCall::glass_call318_getrandom(
// 				bytes.as_mut_ptr().cast(),
// 				bytes.len(),
// 				flags,
// 			);
//
// 			match observation.severity {
// 				Severity::Stable => {
// 					// observation.payload contains bytes written (the return value)
// 					let ret = observation.payload.unwrap_or(0);
// 					if ret > 0 {
// 						bytes = &mut bytes[ret as usize..];
// 					}
// 				}
// 				_ => {
// 					// Escalated observation — extract errno equivalent from Glass state
// 					let err = observation.to_errno();
// 					match err {
// 						libc::libc::EINTR => continue,
// 						// GRND_INSECURE not available, fall back to GRND_NONBLOCK
// 						libc::libc::EINVAL if flags == libc::libc::GRND_INSECURE => {
// 							GRND_INSECURE_AVAILABLE.store(false, Relaxed);
// 							continue;
// 						}
// 						// Pool not initialized, fall back to /dev/urandom
// 						libc::libc::EAGAIN if flags == libc::libc::GRND_NONBLOCK => break,
// 						// getrandom unavailable or blocked by seccomp
// 						libc::libc::ENOSYS | libc::libc::EPERM => {
// 							GETRANDOM_AVAILABLE.store(false, Relaxed);
// 							break;
// 						}
// 						_ => panic!("failed to generate random data"),
// 					}
// 				}
// 			}
// 		}
// 	}
//
// 	// When we want cryptographic strength, wait for CPRNG pool initialization
// 	// by polling /dev/random until ready.
// 	if !insecure {
// 		if !URANDOM_READY.load(Acquire) {
// 			let random = File::open("/dev/random").expect("failed to open /dev/random");
// 			let mut fd = libc::libc::pollfd {
// 				fd: random.as_raw_fd(),
// 				events: libc::libc::POLLIN,
// 				revents: 0,
// 			};
//
// 			while !URANDOM_READY.load(Acquire) {
// 				// TODO: poll could also be routed through DaemonicSystemCall (syscall 7)
// 				// when the full syscall table is implemented
// 				let ret = unsafe { libc::libc::poll(&mut fd, 1, -1) };
// 				match ret {
// 					1 => {
// 						assert_eq!(fd.revents, libc::libc::POLLIN);
// 						URANDOM_READY.store(true, Release);
// 						break;
// 					}
// 					-1 if errno() == libc::libc::EINTR => continue,
// 					_ => panic!("poll(\"/dev/random\") failed"),
// 				}
// 			}
// 		}
// 	}
//
// 	DEVICE
// 		.get_or_try_init(|| File::open("/dev/urandom"))
// 		.and_then(|mut dev| dev.read_exact(bytes))
// 		.expect("failed to generate random data");
// }
//
// pub fn hashmap_random_keys() -> (u64, u64) {
// 	let mut bytes = [0; 16];
// 	getrandom(&mut bytes, true);
// 	let k1 = u64::from_ne_bytes(bytes[..8].try_into().unwrap());
// 	let k2 = u64::from_ne_bytes(bytes[8..].try_into().unwrap());
// 	(k1, k2)
// }
/// `RandomState` is the default state for [`HashMap`] types.
///
/// A particular instance `RandomState` will create the same instances of
/// [`Hasher`], but the hashers created by two different `RandomState`
/// instances are unlikely to produce the same result for the same values.
///
/// [`HashMap`]: crate::collections::HashMap
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use std::hash::RandomState;
///
/// let s = RandomState::new();
/// let mut map = HashMap::with_hasher(s);
/// map.insert(1, 2);
/// ```
#[derive(Clone)]
pub struct RandomState {
	k0: u64,
	k1: u64,
}

impl Frame for RandomState {
	fn frame_type(&self) -> FrameType {
		// Random types are inherently ambiguous on their own
		FrameType::Ambiguous
	}
}

impl ReferenceFrame for RandomState {
	fn origin(&self) -> &TopologySegment {
		todo!("fuck it")
		// &<TopologySegment as TopologyAnchor>::new_anchor("Daemonic::DaemonicHasher::Random::RandomState")
	}
	
	fn transform_to<GLASS>(&self, observation: &impl Glass<GLASS>, target_frame: &dyn ReferenceFrame) -> Option<Observation<GLASS>>
		where
			GLASS: Clone,
			Self: Sized
	{
		todo!()
	}
}
impl SymbolicAnchor for RandomState {
	fn meaningful_within(&self) -> impl ReferenceFrame {
		todo!()
	}
}

impl Anchor for RandomState {
	fn anchor_domains(&self) -> AnchorDomainSet {
		todo!()
	}
}

impl SemanticAnchor for RandomState {}
impl RandomState {
	/// Constructs a new `RandomState` that is initialized with random keys.
	///
	/// # Examples
	///
	/// ```
	/// use std::hash::RandomState;
	///
	/// let s = RandomState::new();
	/// ```
	#[inline]
	#[allow(deprecated)]
	// rand
	#[must_use]
	pub fn new() -> RandomState {
		todo!()
		// Historically this function did not cache keys from the OS and instead
		// simply always called `rand::thread_rng().gen()` twice. In #31356 it
		// was discovered, however, that because we re-seed the thread-local RNG
		// from the OS periodically that this can cause excessive slowdown when
		// many hash maps are created on a thread. To solve this performance
		// trap we cache the first set of randomly generated keys per-thread.
		//
		// Later in #36481 it was discovered that exposing a deterministic
		// iteration order allows a form of DOS attack. To counter that we
		// increment one of the seeds on every RandomState creation, giving
		// every corresponding HashMap a different iteration order.
		//todo: fix this
		// thread_local!(static KEYS: Cell<(u64, u64)> = {
        // Cell::new(hashmap_random_keys())
        // });
		//
		// KEYS.with(|keys| {
		// 	let (k0, k1) = keys.get();
		// 	keys.set((k0.wrapping_add(1), k1));
		// 	RandomState { k0, k1 }
		// })
		
	}
}

impl<GLASS: Glass<GLASS>> BuildHasher<GLASS> for RandomState {
	type Hasher = DefaultDaemonicHasher;
	#[inline]
	#[allow(deprecated)]
	fn build_hasher(&self) -> DefaultDaemonicHasher {
		DefaultDaemonicHasher(DaemonicSipHasher13::new_with_keys(self.k0, self.k1))
	}
}

/// The default [`Hasher`] used by [`RandomState`].
///
/// The internal algorithm is not specified, and so it and its hashes should
/// not be relied upon over releases.
#[allow(deprecated)]
#[derive(Clone, Debug)]
pub struct DefaultDaemonicHasher(DaemonicSipHasher13);
static DEFAULT_DAEMONIC_HASHER_TOPOLOGY_ANCH0R: TopologySegment = TopologySegment {
	label: "Daemonic::DaemonicHasher::DefaultDaemonicHasher",
	hash: const_daemonic_hash(
		"Daemonic::DaemonicHasher::DefaultDaemonicHasher".as_bytes(),
		crate::AXIOM_OFFSET,
	),
	crypto_id: const_daemonic_hash("Daemonic::DaemonicHasher::DefaultDaemonicHasher".as_bytes(), TOPOLOGY_ANCHOR),
	depth: 2u16,
};
impl Glass<DefaultDaemonicHasher> for DefaultDaemonicHasher {
	type Anchor = TopologySegment;
	
	fn position(&self) -> &TopologySegment {
		&DEFAULT_DAEMONIC_HASHER_TOPOLOGY_ANCH0R
	}
	
	fn severity(&self) -> Severity {
		Severity::Unknown
	}
	
	fn payload(&self) -> Option<&DefaultDaemonicHasher> {
		Some(&self)
	}
	
	fn into_payload(self) -> Option<DefaultDaemonicHasher>
		where
			Self: Sized,
			DefaultDaemonicHasher: Sized
	{
		Some(self)
	}
}
impl DefaultDaemonicHasher {
	/// Creates a new `DefaultDaemonicHasher`.
	///
	/// This hasher is not guaranteed to be the same as all other
	/// `DefaultDaemonicHasher` instances, but is the same as all other `DefaultDaemonicHasher`
	/// instances created through `new` or `default`.
	#[inline]
	#[allow(deprecated)]
	#[must_use]
	pub fn new() -> DefaultDaemonicHasher {
		DefaultDaemonicHasher(DaemonicSipHasher13::new_with_keys(0, 0))
	}
}

impl Default for DefaultDaemonicHasher {
	/// Creates a new `DefaultDaemonicHasher` using [`new`].
	/// See its documentation for more.
	///
	/// [`new`]: DefaultDaemonicHasher::new
	#[inline]
	fn default() -> DefaultDaemonicHasher {
		DefaultDaemonicHasher::new()
	}
}

impl<GLASS: Glass<GLASS>> DaemonicHasher<GLASS> for DefaultDaemonicHasher {
	// The underlying `DaemonicSipHasher13` doesn't override the other
	// `write_*` methods, so it's stable not to forward them here.
	//    #[inline]
	//     fn write(&mut self, msg: &[u8]) {
	//         self.0.write(msg)
	//     }
	//
	//     #[inline]
	//     fn write_str(&mut self, s: &str) {
	//         self.0.write_str(s);
	//     }
	//
	//     #[inline]
	//     fn finish(&self) -> u64 {
	//         self.0.finish()
	//     }
	#[inline]
	fn finish(&self) -> u64 {
		// <DaemonicSipHasher13 as DaemonicHasher<GLASS>>::finish(&self.0.finish())
		// let x = self.0.finish();
		<DaemonicSipHasher13 as DaemonicHasher<GLASS>>::finish(&self.0)
	}
	
	#[inline]
	fn write(&mut self, msg: &[u8]) {
		<DaemonicSipHasher13 as DaemonicHasher<GLASS>>::write(&mut self.0, msg)
		// self.0.write(msg)
	}
	
	#[inline]
	fn write_str(&mut self, s: &str) {
		// self.0.write_str(s);
		<DaemonicSipHasher13 as DaemonicHasher<GLASS>>::write_str(&mut self.0, s)
	}
}

impl Default for RandomState {
	/// Constructs a new `RandomState`.
	#[inline]
	fn default() -> RandomState {
		RandomState::new()
	}
}