use alloc::boxed::Box;
use alloc::collections::TryReserveError;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::ffi::CStr;
use core::ops::Deref;
use crate::daemonic::{daemonic_hasher, TopologySegment, TopologyAnchor, AnchorDomainSet};
use crate::daemonic::daemonic_hasher::{DaemonicHashable, DaemonicHasher};
use crate::daemonic::daemonic_hasher::random::DefaultDaemonicHasher;
use crate::daemonic::frame::ReferenceFrame;
use crate::daemonic::glass::Glass;
#[derive(Debug)]
pub struct DaemonicPathBuf {
inner: DaemonicOsString,
}
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/'
}
#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
b == b'/'
}
pub trait DaemonicOsStringExt {
fn from_vec(vec: Vec<u8>) -> Self;
fn into_vec(self) -> Vec<u8>;
}
impl DaemonicOsStringExt for DaemonicOsString {
#[inline]
fn from_vec(vec: Vec<u8>) -> DaemonicOsString {
FromInner::from_inner(DaemonicBuf { inner: vec })
}
#[inline]
fn into_vec(self) -> Vec<u8> {
self.into_inner().inner
}
}
#[inline]
pub fn parse_prefix(_: &DaemonicOsStr) -> Option<Prefix<'_>> {
None
}
use crate::daemonic::glass::daemonic_system_call::c_types::*;
static GETCWD_TOPOLOGY_SEGMENT: TopologySegment = TopologySegment::new("Daemonic::Glass::Floating::fn getcwd() -> Observation<DaemonicPathBuf>");
fn getcwd() -> Observation<DaemonicPathBuf>
where
DaemonicOsString: AsRef<DaemonicPath> + DaemonicSystemCall,
{
use crate::daemonic::glass::daemonic_system_call::DaemonicSystemCall;
let mut buf = Vec::with_capacity(512);
loop {
unsafe {
let ptr = buf.as_mut_ptr() as *mut c_char;
let obs = <DaemonicOsString as DaemonicSystemCall>::glass_call79_getcwd(ptr, buf.capacity() as c_ulong);
match obs.severity {
Severity::Cracked => {
let cap = buf.capacity();
buf.set_len(cap);
buf.reserve(1);
continue;
}
Severity::Stable => {
let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len();
buf.set_len(len);
buf.shrink_to_fit();
let mut fuck_buf = DaemonicPathBuf::new();
fuck_buf.push(DaemonicOsString::from_vec(buf));
return Observation {
position: &GETCWD_TOPOLOGY_SEGMENT,
severity: crate::Severity::Stable,
tier: crate::ObservationTier::Composed,
annotation: crate::Annotation::None,
temporal: crate::Temporal::Current,
payload: Some(DaemonicPathBuf::from(fuck_buf)),
};
}
Severity::Warp => {
return Observation::shattered(&GETCWD_TOPOLOGY_SEGMENT)
.with_note("getcwd: internal error — buffer construction failed. \
EFAULT/EINVAL at this layer indicates a bug in DaemonicError, \
not in your code. Please file an issue: \
https://gitlab.com/Mephistophel3s/daemonic-error");
}
Severity::Fracture => {
return Observation::shattered(&GETCWD_TOPOLOGY_SEGMENT)
.with_note("getcwd: working directory is inaccessible. \
Either the directory was deleted while the process was running \
(ENOENT) or the path exceeds system limits (ENAMETOOLONG).");
}
_ => {
return Observation::shattered(&GETCWD_TOPOLOGY_SEGMENT)
.with_note("getcwd: unexpected error state from syscall 79.");
}
}
}
}
}
pub const MAIN_SEP_STR: &str = "/";
pub const MAIN_SEP: char = '/';
impl<P: AsRef<DaemonicPath>> Extend<P> for DaemonicPathBuf
where
DaemonicPath: AsRef<DaemonicPath>,
{
fn extend<I: IntoIterator<Item=P>>(&mut self, iter: I) {
iter.into_iter().for_each(move |p| self.push(p.as_ref()));
}
#[inline]
fn extend_one(&mut self, p: P) {
self.push(p.as_ref());
}
}
pub(crate) fn absolute(path: &DaemonicPath) -> Observation<DaemonicPathBuf>
where
str: AsRef<daemonic_path::DaemonicPath>,
DaemonicOsString: AsRef<daemonic_path::DaemonicPath>,
DaemonicOsStr: AsRef<daemonic_path::DaemonicPath> + Clone,
{
let mut components = path.strip_prefix(".").unwrap_or(path).components();
let path_os = path.as_os_str().as_encoded_bytes();
let mut normalized = if path.is_absolute() {
if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
components.next();
let slash = DaemonicOsString::from("//").as_ref().clone();
let mut slash_ext = DaemonicPathBuf::new();
slash_ext.push(slash);
DaemonicPathBuf::from(slash_ext)
} else {
let slash = DaemonicOsString::from("/").as_ref().clone();
let mut slash_ext = DaemonicPathBuf::new();
slash_ext.push(slash);
DaemonicPathBuf::from(slash_ext)
}
} else {
getcwd()?
};
normalized.extend(components);
if path_os.ends_with(b"/") {
normalized.push("");
}
Observation {
position: &ABSOLUTE_TOPOLOGY_SEGMENT,
severity: crate::Severity::Stable,
tier: crate::ObservationTier::GlyphicExecutable,
annotation: crate::Annotation::None,
temporal: crate::Temporal::Current,
payload: Some(normalized),
}
}
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum Prefix<'a> {
Verbatim(&'a DaemonicOsStr),
VerbatimUNC(
&'a DaemonicOsStr,
&'a DaemonicOsStr,
),
VerbatimDisk(u8),
DeviceNS(&'a DaemonicOsStr),
UNC(
&'a DaemonicOsStr,
&'a DaemonicOsStr,
),
Disk(u8),
}
impl<'prefix> DaemonicHashable for Prefix<'prefix> {
fn declare_hashable<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&self, state: &mut GLASS) {
match self {
Prefix::Verbatim(DaemonicOsStr) => {
0u8.declare_hashable(state);
DaemonicOsStr.declare_hashable(state);
}
Prefix::VerbatimUNC(DaemonicOsStr1, DaemonicOsStr2) => {
1u8.declare_hashable(state);
DaemonicOsStr1.declare_hashable(state);
DaemonicOsStr2.declare_hashable(state);
}
Prefix::VerbatimDisk(u8) => {
2u8.declare_hashable(state);
u8.declare_hashable(state);
}
Prefix::DeviceNS(DaemonicOsStr) => {
3u8.declare_hashable(state);
DaemonicOsStr.declare_hashable(state);
}
Prefix::UNC(DaemonicOsStr1, DaemonicOsStr2) => {
4u8.declare_hashable(state);
DaemonicOsStr1.declare_hashable(state);
DaemonicOsStr2.declare_hashable(state);
}
Prefix::Disk(u8) => {
5u8.declare_hashable(state);
u8.declare_hashable(state);
}
}
}
}
static ABSOLUTE_TOPOLOGY_SEGMENT: TopologySegment = TopologySegment::new("Daemonic::Glass::Floating::absolute(path: &DaemonicPath) -> Observation<DaemonicPathBuf>");
pub(crate) fn is_absolute(path: &DaemonicPath) -> bool {
if cfg!(any(unix, target_os = "hermit", target_os = "wasi")) {
path.has_root()
} else {
path.has_root() && path.prefix().is_some()
}
}
fn validate_extension(extension: &DaemonicOsStr) {
for &b in extension.as_encoded_bytes() {
if is_sep_byte(b) {
panic!("extension cannot contain path separators: {extension:?}");
}
}
}
impl Deref for DaemonicPathBuf {
type Target = DaemonicPath;
#[inline]
fn deref(&self) -> &DaemonicPath {
self.as_path()
}
}
impl DaemonicPathBuf {
#[must_use]
#[inline]
pub fn new() -> DaemonicPathBuf {
DaemonicPathBuf { inner: DaemonicOsString::new() }
}
#[must_use]
#[inline]
pub fn with_capacity(capacity: usize) -> DaemonicPathBuf {
DaemonicPathBuf { inner: DaemonicOsString::with_capacity(capacity) }
}
#[must_use]
#[inline]
pub fn as_path(&self) -> &DaemonicPath {
DaemonicPath::new(self.inner.as_os_str())
}
#[inline]
pub fn leak<'a>(self) -> &'a mut DaemonicPathBuf {
Box::leak(Box::new(self))
}
unsafe fn from_u8_slice(s: &[u8]) -> &DaemonicPath {
unsafe { DaemonicPath::new(DaemonicOsStr::from_encoded_bytes_unchecked(s)) }
}
pub(crate) fn as_u8_slice(&self) -> &[u8] {
self.inner.as_encoded_bytes()
}
pub fn components(&self) -> Components<'_> {
let prefix = parse_prefix(self.inner.as_os_str());
Components {
path: self.as_u8_slice(),
prefix,
has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
front: State::Prefix,
back: State::Body,
}
}
pub fn push<P: AsRef<DaemonicPath>>(&mut self, path: P) {
self._push(path.as_ref())
}
fn _push(&mut self, path: &DaemonicPath) {
let buf = self.inner.as_encoded_bytes();
let mut need_sep = buf.last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
let comps = self.components();
if comps.prefix_len() > 0
&& comps.prefix_len() == comps.path.len()
&& comps.prefix.unwrap().is_drive()
{
need_sep = false
}
if path.is_absolute() || path.prefix().is_some() {
self.inner.truncate(0);
} else if comps.prefix_verbatim() && !path.inner.is_empty() {
let mut buf: Vec<_> = comps.collect();
for c in path.components() {
match c {
Component::RootDir => {
buf.truncate(1);
buf.push(c);
}
Component::CurDir => (),
Component::ParentDir => {
if let Some(Component::Normal(_)) = buf.last() {
buf.pop();
}
}
_ => buf.push(c),
}
}
let mut res = DaemonicOsString::new();
let mut need_sep = false;
for c in buf {
if need_sep && c != Component::RootDir {
res.push(MAIN_SEP_STR);
}
res.push(c.as_os_str());
need_sep = match c {
Component::RootDir => false,
Component::Prefix(prefix) => {
!prefix.parsed.is_drive() && prefix.parsed.len() > 0
}
_ => true,
}
}
self.inner = res;
return;
} else if path.has_root() {
let prefix_len = self.components().prefix_remaining();
self.inner.truncate(prefix_len);
} else if need_sep {
self.inner.push(MAIN_SEP_STR);
}
self.inner.push(path);
}
pub fn pop(&mut self) -> bool {
match self.parent().map(|p| p.as_u8_slice().len()) {
Some(len) => {
self.inner.truncate(len);
true
}
None => false,
}
}
#[doc(alias = "dirname")]
#[must_use]
pub fn parent(&self) -> Option<&DaemonicPath> {
let mut comps = self.components();
let comp = comps.next_back();
comp.and_then(|p| match p {
Component::Normal(_) | Component::CurDir | Component::ParentDir => {
Some(comps.as_path())
}
_ => None,
})
}
pub fn set_file_name<S: AsRef<DaemonicOsStr>>(&mut self, file_name: S)
where
DaemonicOsStr: AsRef<daemonic_path::DaemonicPath>,
{
self._set_file_name(file_name.as_ref())
}
fn _set_file_name(&mut self, file_name: &DaemonicOsStr)
where
DaemonicOsStr: AsRef<DaemonicPath>,
{
if self.file_name().is_some() { let popped = self.pop();
debug_assert!(popped);
}
self.push(file_name);
}
pub fn set_extension<S: AsRef<DaemonicOsStr>>(&mut self, extension: S) -> bool {
self._set_extension(extension.as_ref())
}
fn _set_extension(&mut self, extension: &DaemonicOsStr) -> bool {
validate_extension(extension);
let file_stem = match self.file_stem() {
None => return false,
Some(f) => f.as_encoded_bytes(),
};
let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();
let start = self.inner.as_encoded_bytes().as_ptr().addr();
self.inner.truncate(end_file_stem.wrapping_sub(start));
let new = extension.as_encoded_bytes();
if !new.is_empty() {
self.inner.reserve_exact(new.len() + 1);
self.inner.push(".");
unsafe { self.inner.extend_from_slice_unchecked(new) };
}
true
}
pub fn add_extension<S: AsRef<DaemonicOsStr>>(&mut self, extension: S) -> bool {
self._add_extension(extension.as_ref())
}
fn _add_extension(&mut self, extension: &DaemonicOsStr) -> bool {
validate_extension(extension);
let file_name = match self.file_name() {
None => return false,
Some(f) => f.as_encoded_bytes(),
};
let new = extension.as_encoded_bytes();
if !new.is_empty() {
let end_file_name = file_name[file_name.len()..].as_ptr().addr();
let start = self.inner.as_encoded_bytes().as_ptr().addr();
self.inner.truncate(end_file_name.wrapping_sub(start));
self.inner.reserve_exact(new.len() + 1);
self.inner.push(".");
unsafe { self.inner.extend_from_slice_unchecked(new) };
}
true
}
#[must_use]
#[inline]
pub fn as_mut_os_string(&mut self) -> &mut DaemonicOsString {
&mut self.inner
}
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub fn into_os_string(self) -> DaemonicOsString {
self.inner
}
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub fn into_boxed_path(self) -> Box<DaemonicPath> {
let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut DaemonicPath;
unsafe { Box::from_raw(rw) }
}
#[must_use]
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional)
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.inner.try_reserve(additional)
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional)
}
#[inline]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.inner.try_reserve_exact(additional)
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit()
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.inner.shrink_to(min_capacity)
}
}
impl Clone for DaemonicPathBuf {
#[inline]
fn clone(&self) -> Self {
DaemonicPathBuf { inner: self.inner.clone() }
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.inner.clone_from(&source.inner)
}
}
use daemonic_path::*;
mod daemonic_path;
use daemonic_os_str::*;
mod daemonic_os_str;
use daemonic_slice::*;
mod daemonic_slice;
use daemonic_buf::*;
use crate::{Observation, Severity};
mod path_components;
use path_components::*;
use crate::daemonic::glass::daemonic_system_call::DaemonicSystemCall;
mod daemonic_buf;
impl DaemonicHashable for Vec<u8> {
fn declare_hashable<GLASS: DaemonicHasher<GLASS> + Glass<GLASS>>(&self, state: &mut GLASS) {
"Vec<u8>".declare_hashable(state);
self.as_slice().declare_hashable(state);
}
}