Add Path/PathBuf + GetRandom
This commit is contained in:
parent
50c182293e
commit
0604df7720
@ -7,9 +7,9 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
|
||||
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }
|
||||
compiler_builtins = { version = "0.1", optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
rustc-dep-of-std = ["core", "alloc", "compiler_builtins/rustc-dep-of-std"]
|
||||
alloc = []
|
||||
rustc-dep-of-std = ["core", "compiler_builtins/rustc-dep-of-std"]
|
||||
|
@ -30,6 +30,12 @@ primitive_enum!(
|
||||
Interrupted = 12,
|
||||
#[doc = "Operation has not completed yet"]
|
||||
WouldBlock = 13,
|
||||
#[doc = "Entry/file cannot be written to"]
|
||||
ReadOnly = 14,
|
||||
#[doc = "Requested operation cannot be performed or is invalid"]
|
||||
InvalidOperation = 15,
|
||||
#[doc = "No permission to access the entry/file"]
|
||||
PermissionDenied = 16,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -10,17 +10,29 @@ pub use terminal::{
|
||||
TerminalInputOptions, TerminalLineOptions, TerminalOptions, TerminalOutputOptions, TerminalSize,
|
||||
};
|
||||
|
||||
use crate::{transparent_wrapper, util::FixedString};
|
||||
|
||||
/// Raw file descriptor representation
|
||||
#[derive(Clone, Copy, PartialEq, Debug, PartialOrd, Ord, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct RawFd(pub u32);
|
||||
|
||||
transparent_wrapper! {
|
||||
#[doc = "Unique per-user number"]
|
||||
pub struct UserId(u32)
|
||||
}
|
||||
|
||||
transparent_wrapper! {
|
||||
#[doc = "Unique per-group number"]
|
||||
pub struct GroupId(u32)
|
||||
}
|
||||
|
||||
/// Raw directory entry representation
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct DirectoryEntry {
|
||||
/// Name of the entry
|
||||
pub name: [u8; 256],
|
||||
pub name: FixedString<256>,
|
||||
/// Type of the entry
|
||||
pub ty: FileType,
|
||||
}
|
||||
@ -78,3 +90,39 @@ impl From<u32> for RawFd {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl UserId {
|
||||
/// Root user identifier
|
||||
pub const fn root() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
||||
/// Returns `true` if the UserId represents a root user
|
||||
pub const fn is_root(&self) -> bool {
|
||||
self.0 == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for UserId {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupId {
|
||||
/// Root group identifier
|
||||
pub const fn root() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
||||
/// Returns `true` if the GroupId represents a root group
|
||||
pub const fn is_root(&self) -> bool {
|
||||
self.0 == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for GroupId {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,12 @@
|
||||
#![feature(trace_macros, const_trait_impl)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
pub(crate) mod macros;
|
||||
pub mod pass;
|
||||
pub mod util;
|
||||
|
||||
pub mod arch;
|
||||
pub mod error;
|
||||
|
@ -61,6 +61,12 @@ macro_rules! bitflags_impl_common {
|
||||
pub const fn contains(self, bits: $name) -> bool {
|
||||
self.0 & bits.bits() == bits.bits()
|
||||
}
|
||||
|
||||
/// Returns `true` if the value contains any of the bits in `bits`
|
||||
#[inline]
|
||||
pub const fn contains_any(self, bits: $name) -> bool {
|
||||
self.0 & bits.bits() != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$repr> for $name {
|
||||
@ -189,3 +195,31 @@ macro_rules! bitflags {
|
||||
$crate::bitflags_impl_default!($name, $repr$(, $struct_default)?);
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a #[repr(transparent)] wrapper for a value with Debug, Copy, Eq, Ord, Hash derived +
|
||||
/// Into<T> implemented
|
||||
#[macro_export]
|
||||
macro_rules! transparent_wrapper {
|
||||
($(#[$struct_meta:meta])* $vis:vis struct $name:ident ( $ty:ty )) => {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
$(#[$struct_meta])* $vis struct $name ($ty);
|
||||
|
||||
impl $name {
|
||||
/// Constructs the value from its raw representation.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: the actual subset of values represented by this type may not include all
|
||||
/// the raw values.
|
||||
pub unsafe fn from_raw(value: $ty) -> $name {
|
||||
$name(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for $ty {
|
||||
fn from(value: $name) -> $ty {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
29
src/path.rs
29
src/path.rs
@ -1,29 +0,0 @@
|
||||
//! Filesystem path definitions and manipulation functions
|
||||
|
||||
/// Parent directory path element
|
||||
pub const PARENT_NAME: &str = "..";
|
||||
/// Path element that refers to itself
|
||||
pub const SELF_NAME: &str = ".";
|
||||
|
||||
/// String representation of a path separator
|
||||
pub const SEPARATOR_STR: &str = "/";
|
||||
/// Character that separates the path elements
|
||||
pub const SEPARATOR: char = '/';
|
||||
|
||||
/// Splits a path, returning the first element and the rest
|
||||
pub fn split_left(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.split_once(SEPARATOR) {
|
||||
(left, right.trim_start_matches(SEPARATOR))
|
||||
} else {
|
||||
(path, "")
|
||||
}
|
||||
}
|
||||
|
||||
/// Splits a path, returning the last element and the path preceding it
|
||||
pub fn split_right(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.trim_end_matches(SEPARATOR).rsplit_once(SEPARATOR) {
|
||||
(left.trim_end_matches(SEPARATOR), right)
|
||||
} else {
|
||||
("", path)
|
||||
}
|
||||
}
|
11
src/path/mod.rs
Normal file
11
src/path/mod.rs
Normal file
@ -0,0 +1,11 @@
|
||||
//! Filesystem path definitions and manipulation functions
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
mod path;
|
||||
#[cfg(feature = "alloc")]
|
||||
mod path_buf;
|
||||
|
||||
pub use path::Path;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use path_buf::PathBuf;
|
87
src/path/path.rs
Normal file
87
src/path/path.rs
Normal file
@ -0,0 +1,87 @@
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct Path(str);
|
||||
|
||||
impl Path {
|
||||
pub const SEPARATOR: char = '/';
|
||||
pub const SEPARATOR_STR: &'static str = "/";
|
||||
|
||||
/// Parent directory path element
|
||||
pub const PARENT_NAME: &'static str = "..";
|
||||
/// Path element that refers to itself
|
||||
pub const SELF_NAME: &'static str = ".";
|
||||
|
||||
pub fn from_str(s: &str) -> &Self {
|
||||
unsafe { core::mem::transmute(s) }
|
||||
}
|
||||
|
||||
pub fn empty() -> &'static Self {
|
||||
Self::from_str("")
|
||||
}
|
||||
|
||||
pub fn trim_start_separators(&self) -> &Self {
|
||||
Self::from_str(self.0.trim_start_matches(Self::SEPARATOR))
|
||||
}
|
||||
|
||||
pub fn trim_end_separators(&self) -> &Self {
|
||||
Self::from_str(self.0.trim_end_matches(Self::SEPARATOR))
|
||||
}
|
||||
|
||||
pub fn display(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn split_right(&self) -> (&Path, &str) {
|
||||
if let Some((left, right)) = self
|
||||
.0
|
||||
.trim_end_matches(Self::SEPARATOR)
|
||||
.rsplit_once(Self::SEPARATOR)
|
||||
{
|
||||
(
|
||||
Path::from_str(left.trim_end_matches(Self::SEPARATOR)),
|
||||
right,
|
||||
)
|
||||
} else {
|
||||
(Path::empty(), &self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split_left(&self) -> (&str, &Path) {
|
||||
if let Some((left, right)) = self.0.split_once(Self::SEPARATOR) {
|
||||
(
|
||||
left,
|
||||
Path::from_str(right.trim_start_matches(Self::SEPARATOR)),
|
||||
)
|
||||
} else {
|
||||
(&self.0, Path::empty())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_absolute(&self) -> bool {
|
||||
self.0.starts_with(Self::SEPARATOR)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Path {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for Path {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for str {
|
||||
fn as_ref(&self) -> &Path {
|
||||
Path::from_str(self)
|
||||
}
|
||||
}
|
67
src/path/path_buf.rs
Normal file
67
src/path/path_buf.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use crate::path::Path;
|
||||
use alloc::{
|
||||
borrow::{Borrow, ToOwned},
|
||||
string::String,
|
||||
};
|
||||
use core::ops::Deref;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct PathBuf(String);
|
||||
|
||||
impl PathBuf {
|
||||
pub fn new() -> Self {
|
||||
Self(String::new())
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Self {
|
||||
Self(String::from(s))
|
||||
}
|
||||
|
||||
pub fn push<P: AsRef<Path>>(&mut self, path: P) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn display(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PathBuf {
|
||||
type Target = Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
Path::from_str(self.0.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for PathBuf {
|
||||
fn as_ref(&self) -> &Path {
|
||||
Path::from_str(self.0.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Path> for PathBuf {
|
||||
fn from(value: &Path) -> Self {
|
||||
Self::from_str(value.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for PathBuf {
|
||||
fn from(value: &str) -> Self {
|
||||
Self::from_str(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOwned for Path {
|
||||
type Owned = PathBuf;
|
||||
|
||||
fn to_owned(&self) -> Self::Owned {
|
||||
PathBuf::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<Path> for PathBuf {
|
||||
fn borrow(&self) -> &Path {
|
||||
Path::from_str(self.0.as_str())
|
||||
}
|
||||
}
|
@ -4,30 +4,30 @@ use crate::primitive_enum;
|
||||
primitive_enum!(
|
||||
#[doc = "Describes a system call issued to the kernel"]
|
||||
pub enum SyscallFunction: usize {
|
||||
#[doc = "Terminate the caller thread"]
|
||||
Exit = 1,
|
||||
#[doc = "Suspend the caller task for some time"]
|
||||
Nanosleep = 2,
|
||||
Nanosleep = 1,
|
||||
#[doc = "Map a virtual memory region"]
|
||||
MapMemory = 3,
|
||||
MapMemory = 2,
|
||||
#[doc = "Release a virtual memory region"]
|
||||
UnmapMemory = 4,
|
||||
UnmapMemory = 3,
|
||||
#[doc = "Write data to a file descriptor"]
|
||||
Write = 5,
|
||||
Write = 4,
|
||||
#[doc = "Read data from a file descriptor"]
|
||||
Read = 6,
|
||||
Read = 5,
|
||||
#[doc = "Open a file"]
|
||||
Open = 7,
|
||||
Open = 6,
|
||||
#[doc = "Close a file descriptor"]
|
||||
Close = 8,
|
||||
Close = 7,
|
||||
#[doc = "Open a directory for reading"]
|
||||
OpenDirectory = 9,
|
||||
OpenDirectory = 8,
|
||||
#[doc = "Read entries from a directory descriptor"]
|
||||
ReadDirectory = 10,
|
||||
ReadDirectory = 9,
|
||||
#[doc = "Create a directory"]
|
||||
CreateDirectory = 11,
|
||||
#[doc = "Remove a file, directory or other entry"]
|
||||
Remove = 12,
|
||||
CreateDirectory = 10,
|
||||
#[doc = "Remove a file"]
|
||||
Remove = 11,
|
||||
#[doc = "Remove a directory"]
|
||||
RemoveDirectory = 12,
|
||||
#[doc = "Retrieves metadata for a filesystem entry"]
|
||||
GetMetadata = 13,
|
||||
#[doc = "Seek a file descriptor to the specified position"]
|
||||
@ -60,6 +60,10 @@ primitive_enum!(
|
||||
SetSignalEntry = 51,
|
||||
#[doc = "Exit from a syscall handler"]
|
||||
ExitSignal = 52,
|
||||
#[doc = "Terminate the caller thread"]
|
||||
ExitThread = 53,
|
||||
#[doc = "Terminate the caller process"]
|
||||
ExitProcess = 54,
|
||||
|
||||
#[doc = "Mount a filesystem"]
|
||||
Mount = 101,
|
||||
@ -68,5 +72,7 @@ primitive_enum!(
|
||||
|
||||
#[doc = "Print a message to the kernel's debug trace output"]
|
||||
DebugTrace = 128,
|
||||
#[doc = "Fetches bytes of random data"]
|
||||
GetRandom = 129,
|
||||
}
|
||||
);
|
||||
|
58
src/util.rs
Normal file
58
src/util.rs
Normal file
@ -0,0 +1,58 @@
|
||||
//! Misc utilities for the ABI crate
|
||||
|
||||
use crate::error::Error;
|
||||
use core::{fmt, str::FromStr};
|
||||
|
||||
/// Helper struct to hold a fixed-size string of UTF-8 characters
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct FixedString<const N: usize> {
|
||||
data: [u8; N],
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<const N: usize> FixedString<N> {
|
||||
/// Returns an empty [FixedString]
|
||||
pub const fn empty() -> Self {
|
||||
Self {
|
||||
data: [0; N],
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> fmt::Debug for FixedString<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(self.as_ref(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> AsRef<str> for FixedString<N> {
|
||||
fn as_ref(&self) -> &str {
|
||||
// Safety: totally safe, the FixedString can only be constructed from a &str or be empty
|
||||
unsafe { core::str::from_utf8_unchecked(&self.data[..self.len]) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> FromStr for FixedString<N> {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.len() >= N {
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
let len = s.len();
|
||||
let mut data = [0; N];
|
||||
data[..len].copy_from_slice(s.as_bytes());
|
||||
Ok(Self { data, len })
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> PartialEq<&str> for FixedString<N> {
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
&self.data[..self.len] == other.as_bytes()
|
||||
}
|
||||
|
||||
fn ne(&self, other: &&str) -> bool {
|
||||
&self.data[..self.len] != other.as_bytes()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user