1use core::{cell::UnsafeCell, mem::MaybeUninit, ptr::NonNull};
5use safa_abi::raw::{NonNullSlice, Optional};
6
7#[derive(Debug, Clone, Copy)]
10pub(super) struct RawArgs {
11 args: NonNull<[NonNullSlice<u8>]>,
12}
13
14impl RawArgs {
15 pub const fn new(args: NonNull<[NonNullSlice<u8>]>) -> Self {
16 Self { args }
17 }
18
19 fn len(&self) -> usize {
20 unsafe { self.args.as_ref().len() }
21 }
22
23 fn get(&self, index: usize) -> Option<NonNullSlice<u8>> {
24 unsafe { self.args.as_ref().get(index).copied() }
25 }
26
27 unsafe fn into_slice(self) -> &'static [NonNullSlice<u8>] {
28 unsafe { self.args.as_ref() }
29 }
30}
31
32pub(super) struct RawArgsStatic(UnsafeCell<MaybeUninit<Option<RawArgs>>>);
33unsafe impl Sync for RawArgsStatic {}
34
35impl RawArgsStatic {
36 pub const fn new() -> Self {
37 Self(UnsafeCell::new(MaybeUninit::uninit()))
38 }
39
40 pub unsafe fn init(&self, args: Option<RawArgs>) {
41 unsafe {
42 self.0.get().write(MaybeUninit::new(args));
43 }
44 }
45
46 unsafe fn get(&self, index: usize) -> Option<NonNullSlice<u8>> {
47 unsafe { (*self.0.get()).assume_init()?.get(index) }
48 }
49
50 unsafe fn len(&self) -> usize {
51 if let Some(args) = unsafe { (*self.0.get()).assume_init() } {
52 args.len()
53 } else {
54 0
55 }
56 }
57
58 unsafe fn get_raw(&self) -> Option<RawArgs> {
59 unsafe { (*self.0.get()).assume_init() }
60 }
61
62 pub unsafe fn as_slice(&self) -> &'static [NonNullSlice<u8>] {
63 unsafe {
64 if let Some(raw) = self.get_raw() {
65 raw.into_slice()
66 } else {
67 &mut []
68 }
69 }
70 }
71}
72
73pub(super) static RAW_ARGS: RawArgsStatic = RawArgsStatic::new();
74
75#[cfg_attr(
77 not(any(feature = "std", feature = "rustc-dep-of-std")),
78 unsafe(no_mangle)
79)]
80#[inline(always)]
81pub extern "C" fn sysget_argc() -> usize {
82 unsafe { RAW_ARGS.len() }
83}
84
85#[cfg_attr(
87 not(any(feature = "std", feature = "rustc-dep-of-std")),
88 unsafe(no_mangle)
89)]
90#[inline(always)]
91pub extern "C" fn sysget_arg(index: usize) -> Optional<NonNullSlice<u8>> {
92 unsafe { RAW_ARGS.get(index).into() }
93}
94
95pub struct ArgsIter {
97 args: &'static [NonNullSlice<u8>],
98 index: usize,
99}
100
101impl ArgsIter {
102 pub fn get() -> Self {
103 let args = unsafe { RAW_ARGS.as_slice() };
104 Self { args, index: 0 }
105 }
106
107 pub fn get_index(&self, index: usize) -> Option<NonNullSlice<u8>> {
108 self.args.get(index).copied()
109 }
110
111 pub fn next(&mut self) -> Option<NonNullSlice<u8>> {
112 if self.index < self.args.len() {
113 let arg = self.args[self.index];
114 self.index += 1;
115 Some(arg)
116 } else {
117 None
118 }
119 }
120 pub fn total_len(&self) -> usize {
122 self.args.len()
123 }
124 pub fn len(&self) -> usize {
126 self.total_len() - self.index
127 }
128}