1use safa_abi::ffi::{option::OptZero, str::Str};
5
6use crate::exported_func;
7use core::{cell::UnsafeCell, mem::MaybeUninit, ptr::NonNull};
8
9#[derive(Debug, Clone, Copy)]
12pub(super) struct RawArgs {
13 args: NonNull<[&'static str]>,
14}
15
16impl RawArgs {
17 pub const fn new(args: Option<NonNull<[&'static str]>>) -> Self {
18 Self {
19 args: match args {
20 Some(args) => args,
21 None => unsafe { NonNull::new_unchecked(&mut []) },
22 },
23 }
24 }
25
26 const fn len(&self) -> usize {
27 unsafe { self.args.as_ref().len() }
28 }
29
30 fn get(&self, index: usize) -> Option<&'static str> {
31 unsafe { self.args.as_ref().get(index).copied() }
32 }
33
34 const unsafe fn into_slice(self) -> &'static [&'static str] {
35 unsafe { self.args.as_ref() }
36 }
37}
38
39pub(super) struct RawArgsStatic(UnsafeCell<MaybeUninit<RawArgs>>);
40unsafe impl Sync for RawArgsStatic {}
41
42impl RawArgsStatic {
43 pub const fn new() -> Self {
44 Self(UnsafeCell::new(MaybeUninit::uninit()))
45 }
46
47 pub unsafe fn init(&self, args: RawArgs) {
48 unsafe {
49 self.0.get().write(MaybeUninit::new(args));
50 }
51 }
52
53 const unsafe fn get_unchecked(&self) -> &mut RawArgs {
54 (*self.0.get()).assume_init_mut()
55 }
56
57 unsafe fn get(&self, index: usize) -> Option<&'static str> {
58 unsafe { self.get_unchecked().get(index) }
59 }
60
61 const unsafe fn len(&self) -> usize {
62 unsafe { self.get_unchecked().len() }
63 }
64
65 pub const unsafe fn as_slice(&self) -> &'static [&'static str] {
66 unsafe {
67 let raw = self.get_unchecked();
68 raw.into_slice()
69 }
70 }
71}
72
73pub(super) static RAW_ARGS: RawArgsStatic = RawArgsStatic::new();
74
75exported_func! {
76 pub extern "C" fn sysget_argc() -> usize {
78 unsafe { RAW_ARGS.len() }
79 }
80}
81
82exported_func! {
83 pub extern "C" fn sysget_arg(index: usize) -> OptZero<Str> {
85 unsafe { RAW_ARGS.get(index).map(|s| Str::from_str(s)).into() }
86 }
87}
88
89pub struct ArgsIter {
91 args: &'static [&'static str],
92 index: usize,
93}
94
95impl ArgsIter {
96 pub fn get() -> Self {
97 let args = unsafe { RAW_ARGS.as_slice() };
98 Self { args, index: 0 }
99 }
100
101 pub fn get_index(&self, index: usize) -> Option<&'static str> {
102 self.args.get(index).copied()
103 }
104
105 pub fn next(&mut self) -> Option<&'static str> {
106 if self.index < self.args.len() {
107 let arg = self.args[self.index];
108 self.index += 1;
109 Some(arg)
110 } else {
111 None
112 }
113 }
114 pub fn total_len(&self) -> usize {
116 self.args.len()
117 }
118 pub fn len(&self) -> usize {
120 self.total_len() - self.index
121 }
122}