tci/util/
general.rs

1use super::term::*;
2use crate::filedb::*;
3use alloc::alloc::Layout;
4use core::sync::atomic::AtomicUsize;
5use core::{fmt, mem, ops, slice, str};
6use serde::ser::{Serialize, SerializeStruct, Serializer};
7
8pub use aliu::*;
9pub use core::fmt::Write;
10pub use std::collections::VecDeque;
11
12#[allow(unused_macros)]
13macro_rules! panic {
14    ( $( $arg:tt )* ) => {{
15        debug!( $( $arg )* );
16        core::panic!();
17    }};
18}
19
20#[allow(unused_macros)]
21macro_rules! unimplemented {
22    ( $( $arg:tt )* ) => {{
23        debug!( $( $arg )* );
24        core::panic!();
25    }};
26}
27
28#[allow(unused_macros)]
29macro_rules! unreachable {
30    ( $( $arg:tt )* ) => {{
31        debug!( $( $arg )* );
32        core::panic!();
33    }};
34}
35
36#[allow(unused_macros)]
37macro_rules! println {
38    ( $( $arg:tt )* ) => {{
39        debug!( $( $arg )* );
40    }};
41}
42
43#[allow(unused_macros)]
44macro_rules! debug {
45    ($fmt:literal) => {{
46         out!($fmt);
47    }};
48    ($fmt:literal, $( $e:expr ),+ ) => {{
49         out!(@DEBUG, $fmt, $( $e ),+ );
50    }};
51    ($expr:expr) => {{
52         out!(@DEBUG, "{} = {:?}", stringify!($expr), $expr);
53    }};
54    () => {{
55        out!("Nothing to see here");
56    }};
57}
58
59#[cfg(target_arch = "wasm32")]
60pub static OUTPUT: Option<&'static (dyn Fn(String) + Sync)> = None;
61
62pub static COUNTER: AtomicUsize = AtomicUsize::new(0);
63pub const LIMIT: usize = usize::MAX;
64
65#[allow(unused_macros)]
66macro_rules! out {
67    ($str:literal) => {{
68        out!(@DEBUG, "{}", $str);
69    }};
70    (@DEBUG, $str:expr, $( $e:expr ),+ ) => {{
71        if cfg!(debug_assertions) {
72            out!(@LIMITED, core::concat!("DEBUG ({}:{}): ", $str, "\n"), file!(), line!(), $( $e ),+ );
73        }
74    }};
75    (@LOG, $str:expr, $( $e:expr ),+ ) => {{
76        out!(@CLEAN, core::concat!("LOG ({}:{}): ", $str, "\n"), file!(), line!(), $( $e ),+ );
77    }};
78    (@LIMITED, $str:expr, $( $e:expr ),+ ) => {{
79        let count = $crate::COUNTER.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
80        if count > $crate::LIMIT {
81            out!(@CLEAN, "{}", "debug statement limit reached");
82            core::panic!();
83        }
84
85        out!(@CLEAN, core::concat!("{:<3} ", $str), count, $( $e ),+ );
86    }};
87    (@CLEAN, $str:expr, $( $e:expr ),+ ) => {{
88        let s = alloc::format!( $str, $( $e ),+ );
89
90        #[cfg(all(not(target_arch = "wasm32"), not(test)))]
91        libc_print::libc_print!("{}", s);
92
93        #[cfg(test)]
94        std::print!("{}", s);
95
96        #[allow(unused_unsafe)]
97        #[cfg(target_arch = "wasm32")]
98        if let Some(func) = unsafe { core::ptr::read_volatile(&$crate::OUTPUT) } {
99            func(s);
100
101        }
102    }};
103}
104
105#[cfg(target_arch = "wasm32")]
106pub fn register_output(f: impl Fn(String) + 'static) {
107    let out = &OUTPUT as *const Option<_> as *mut Option<&'static (dyn Fn(String) + Sync)>;
108    let value: &(dyn Fn(String) + 'static) = Box::leak(Box::new(f));
109
110    unsafe { core::ptr::write_volatile(out, Some(mem::transmute(value))) };
111}
112
113macro_rules! error {
114    ($arg1:expr) => {{
115        let mut s = $arg1.to_string();
116        if cfg!(debug_assertions) {
117            s.push_str(&format!(" (in compiler at {}:{})", file!(), line!()));
118        }
119
120        $crate::util::Error::new(s, vec![])
121    }};
122
123    ($msg:expr, $loc1:expr, $msg1:expr) => {{
124        let mut s = $msg.to_string();
125        if cfg!(debug_assertions) {
126            s.push_str(&format!(" (in compiler at {}:{})", file!(), line!()));
127        }
128
129        $crate::util::Error::new(
130            s,
131            vec![$crate::util::ErrorSection {
132                location: $loc1,
133                message: $msg1.to_string(),
134            }],
135        )
136    }};
137
138    ($msg:expr, $loc1:expr, $msg1:expr, $loc2:expr, $msg2:expr) => {{
139        let mut s = $msg.to_string();
140        if cfg!(debug_assertions) {
141            s += &format!(" (in compiler at {}:{})", file!(), line!());
142        }
143
144        $crate::util::Error::new(
145            s,
146            vec![
147                $crate::util::ErrorSection {
148                    location: $loc1,
149                    message: $msg1.to_string(),
150                },
151                $crate::util::ErrorSection {
152                    location: $loc2,
153                    message: $msg2.to_string(),
154                },
155            ],
156        )
157    }};
158}
159
160#[derive(Debug, serde::Serialize)]
161pub struct ErrorSection {
162    pub location: CodeLoc,
163    pub message: String,
164}
165
166impl Into<Label> for &ErrorSection {
167    fn into(self) -> Label {
168        Label::new(self.location.file, self.location).with_message(&self.message)
169    }
170}
171
172#[derive(Debug, serde::Serialize)]
173pub struct Error {
174    pub message: String,
175    pub sections: Vec<ErrorSection>,
176}
177
178impl Error {
179    pub fn new(message: String, sections: Vec<ErrorSection>) -> Error {
180        Self {
181            message: message,
182            sections,
183        }
184    }
185
186    pub fn render(&self, files: &FileDb, out: &mut impl Write) -> fmt::Result {
187        Diagnostic::new()
188            .with_message(&self.message)
189            .with_labels(self.sections.iter().map(|x| x.into()).collect())
190            .render(files, out)
191    }
192}
193
194impl Into<Vec<Error>> for Error {
195    fn into(self) -> Vec<Error> {
196        vec![self]
197    }
198}
199
200pub const NO_FILE: CodeLoc = CodeLoc {
201    start: 0,
202    end: 0,
203    file: !0,
204};
205
206#[derive(Clone, Copy, Hash, PartialEq, Eq)]
207pub struct CodeLoc {
208    pub start: u32, // TODO Top 20 bits for start, bottom 12 bits for length?
209    pub end: u32,
210    pub file: u32,
211}
212
213impl Serialize for CodeLoc {
214    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
215    where
216        S: Serializer,
217    {
218        if self == &NO_FILE {
219            return serializer.serialize_none();
220        }
221
222        let mut state = serializer.serialize_struct("CodeLoc", 3)?;
223        state.serialize_field("start", &self.start)?;
224        state.serialize_field("end", &self.end)?;
225        state.serialize_field("file", &self.file)?;
226        return state.end();
227    }
228}
229
230impl fmt::Debug for CodeLoc {
231    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
232        write!(fmt, "{}:({},{})", self.file, self.start, self.end)
233    }
234}
235
236#[inline]
237pub fn l(start: u32, end: u32, file: u32) -> CodeLoc {
238    debug_assert!(start <= end);
239
240    CodeLoc { start, end, file }
241}
242
243impl Into<ops::Range<usize>> for CodeLoc {
244    fn into(self) -> ops::Range<usize> {
245        (self.start as usize)..(self.end as usize)
246    }
247}
248
249#[inline]
250pub fn l_from(loc1: CodeLoc, loc2: CodeLoc) -> CodeLoc {
251    if loc1 == NO_FILE {
252        return loc2;
253    }
254
255    if loc2 == NO_FILE {
256        return loc1;
257    }
258
259    debug_assert_eq!(loc1.file, loc2.file);
260    l(loc1.start, loc2.end, loc1.file)
261}
262
263pub fn align_usize(size: usize, align: usize) -> usize {
264    if size == 0 {
265        return 0;
266    }
267
268    ((size - 1) / align * align) + align
269}
270
271pub fn align_u32(size: u32, align: u32) -> u32 {
272    if size == 0 {
273        return 0;
274    }
275
276    let result = ((size - 1) / align * align) + align;
277    return result;
278}
279
280pub fn align_u64(size: u64, align: u64) -> u64 {
281    if size == 0 {
282        return 0;
283    }
284
285    ((size - 1) / align * align) + align
286}
287
288// https://stackoverflow.com/questions/28127165/how-to-convert-struct-to-u8
289pub unsafe fn any_as_u8_slice_mut<T: Sized + Copy>(p: &mut T) -> &mut [u8] {
290    core::slice::from_raw_parts_mut(p as *mut T as *mut u8, mem::size_of::<T>())
291}
292
293pub fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
294    unsafe { core::slice::from_raw_parts(p as *const T as *const u8, mem::size_of::<T>()) }
295}
296
297pub fn u8_slice_as_any<T: Sized>(p: &[u8]) -> &T {
298    assert_eq!(mem::size_of::<T>(), p.len());
299    unsafe { &*(p.as_ptr() as *const T) }
300}
301
302pub fn u32_to_u32_tup(value: u32) -> (u32, u32) {
303    ((value >> 16) as u32, value as u32)
304}
305
306pub fn fold_binary<I, Iter: Iterator<Item = I>>(
307    mut iter: Iter,
308    mut reducer: impl FnMut(I, I) -> I,
309) -> Option<I> {
310    let first = iter.next()?;
311    let second = match iter.next() {
312        Some(s) => s,
313        None => return Some(first),
314    };
315
316    let mut source = Vec::new();
317    source.push(reducer(first, second));
318
319    loop {
320        let first = match iter.next() {
321            Some(f) => f,
322            None => break,
323        };
324
325        let val = match iter.next() {
326            Some(e) => reducer(first, e),
327            None => first,
328        };
329
330        source.push(val);
331    }
332
333    let mut target = Vec::new();
334    loop {
335        let mut iter = source.into_iter();
336
337        let first = iter.next().unwrap();
338        let second = match iter.next() {
339            Some(s) => s,
340            None => return Some(first),
341        };
342
343        target.push(reducer(first, second));
344
345        loop {
346            let first = match iter.next() {
347                Some(f) => f,
348                None => break,
349            };
350
351            let val = match iter.next() {
352                Some(e) => reducer(first, e),
353                None => first,
354            };
355
356            target.push(val);
357        }
358
359        source = target;
360        target = Vec::new();
361    }
362}
363
364// pub struct Cursor<IO: fmt::Write> {
365//     pub io: IO,
366//     pub len: usize,
367// }
368//
369// impl<IO: fmt::Write> Cursor<IO> {
370//     pub fn new(io: IO) -> Self {
371//         Self { io, len: 0 }
372//     }
373// }
374//
375// impl<IO: fmt::Write> fmt::Write for Cursor<IO> {
376//     fn write_str(&mut self, buf: &str) -> fmt::Result {
377//         let len = self.io.write_str(buf)?;
378//         self.len += len;
379//         return Ok(());
380//     }
381// }
382
383pub struct Void {
384    unused: (),
385}
386
387impl Void {
388    pub fn new() -> Self {
389        return Self { unused: () };
390    }
391}
392
393impl fmt::Write for Void {
394    fn write_str(&mut self, buf: &str) -> fmt::Result {
395        Ok(())
396    }
397}
398
399// https://tools.ietf.org/html/rfc3629
400static UTF8_CHAR_WIDTH: [u8; 256] = [
401    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
402    1, // 0x1F
403    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
404    1, // 0x3F
405    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
406    1, // 0x5F
407    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
408    1, // 0x7F
409    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
410    0, // 0x9F
411    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412    0, // 0xBF
413    0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
414    2, // 0xDF
415    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
416    4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
417];
418
419pub struct Utf8Lossy {
420    bytes: [u8],
421}
422
423impl Utf8Lossy {
424    pub fn from_str(s: &str) -> &Utf8Lossy {
425        Utf8Lossy::from_bytes(s.as_bytes())
426    }
427
428    pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
429        // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required.
430        unsafe { core::mem::transmute(bytes) }
431    }
432
433    pub fn chunks(&self) -> Utf8LossyChunksIter<'_> {
434        Utf8LossyChunksIter {
435            source: &self.bytes,
436        }
437    }
438}
439
440pub struct Utf8LossyChunksIter<'a> {
441    source: &'a [u8],
442}
443
444pub struct Utf8LossyChunk<'a> {
445    /// Sequence of valid chars.
446    /// Can be empty between broken UTF-8 chars.
447    pub valid: &'a str,
448    /// Single broken char, empty if none.
449    /// Empty iff iterator item is last.
450    pub broken: &'a [u8],
451}
452
453impl<'a> Utf8LossyChunksIter<'a> {
454    fn next(&mut self) -> Utf8LossyChunk<'a> {
455        if self.source.is_empty() {
456            return Utf8LossyChunk {
457                valid: "",
458                broken: self.source,
459            };
460        }
461
462        const TAG_CONT_U8: u8 = 128;
463        fn safe_get(xs: &[u8], i: usize) -> u8 {
464            *xs.get(i).unwrap_or(&0)
465        }
466
467        let mut i = 0;
468        while i < self.source.len() {
469            let i_ = i;
470
471            // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and
472            // only increases, so `0 <= i < self.source.len()`.
473            let byte = unsafe { *self.source.get_unchecked(i) };
474            i += 1;
475
476            if byte < 128 {
477            } else {
478                let w = UTF8_CHAR_WIDTH[byte as usize];
479
480                macro_rules! error {
481                    () => {{
482                        // SAFETY: We have checked up to `i` that source is valid UTF-8.
483                        unsafe {
484                            let r = Utf8LossyChunk {
485                                valid: core::str::from_utf8_unchecked(&self.source[0..i_]),
486                                broken: &self.source[i_..i],
487                            };
488                            self.source = &self.source[i..];
489                            return r;
490                        }
491                    }};
492                }
493
494                match w {
495                    2 => {
496                        if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
497                            error!();
498                        }
499                        i += 1;
500                    }
501                    3 => {
502                        match (byte, safe_get(self.source, i)) {
503                            (0xE0, 0xA0..=0xBF) => (),
504                            (0xE1..=0xEC, 0x80..=0xBF) => (),
505                            (0xED, 0x80..=0x9F) => (),
506                            (0xEE..=0xEF, 0x80..=0xBF) => (),
507                            _ => {
508                                error!();
509                            }
510                        }
511                        i += 1;
512                        if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
513                            error!();
514                        }
515                        i += 1;
516                    }
517                    4 => {
518                        match (byte, safe_get(self.source, i)) {
519                            (0xF0, 0x90..=0xBF) => (),
520                            (0xF1..=0xF3, 0x80..=0xBF) => (),
521                            (0xF4, 0x80..=0x8F) => (),
522                            _ => {
523                                error!();
524                            }
525                        }
526                        i += 1;
527                        if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
528                            error!();
529                        }
530                        i += 1;
531                        if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
532                            error!();
533                        }
534                        i += 1;
535                    }
536                    _ => {
537                        error!();
538                    }
539                }
540            }
541        }
542
543        let r = Utf8LossyChunk {
544            // SAFETY: We have checked that the entire source is valid UTF-8.
545            valid: unsafe { core::str::from_utf8_unchecked(self.source) },
546            broken: &[],
547        };
548        self.source = &[];
549        r
550    }
551}
552
553pub fn string_append_utf8_lossy(string: &mut String, bytes: &[u8]) {
554    string.reserve(bytes.len());
555    let mut iter = Utf8Lossy::from_bytes(bytes).chunks();
556
557    const REPLACEMENT: &str = "\u{FFFD}";
558
559    loop {
560        let Utf8LossyChunk { valid, broken } = iter.next();
561        string.push_str(valid);
562        if !broken.is_empty() {
563            string.push_str(REPLACEMENT);
564        } else {
565            return;
566        }
567    }
568}
569
570pub fn write_utf8_lossy(mut write: impl fmt::Write, bytes: &[u8]) -> fmt::Result {
571    let mut iter = Utf8Lossy::from_bytes(bytes).chunks();
572
573    const REPLACEMENT: &str = "\u{FFFD}";
574
575    let mut total = 0;
576    loop {
577        let Utf8LossyChunk { valid, broken } = iter.next();
578        write.write_str(valid)?;
579        total += valid.len();
580        if !broken.is_empty() {
581            write.write_str(REPLACEMENT)?;
582            total += REPLACEMENT.len();
583        } else {
584            return Ok(());
585        }
586    }
587}
588
589#[allow(non_camel_case_types)]
590#[derive(Clone, Copy, PartialEq, Eq, Hash)]
591#[repr(C)]
592pub struct n32 {
593    pub data: u32,
594}
595
596impl n32 {
597    pub const NULL: n32 = n32 { data: !0 };
598
599    pub fn new(data: u32) -> Self {
600        if data == Self::NULL.data {
601            panic!("NullPointerException");
602        }
603
604        Self { data }
605    }
606
607    pub fn opt(self) -> Option<u32> {
608        if self.data == Self::NULL.data {
609            return None;
610        }
611
612        return Some(self.data);
613    }
614
615    pub fn ok_or_else<T, F>(self, f: F) -> Result<u32, T>
616    where
617        F: FnOnce() -> T,
618    {
619        if self == Self::NULL {
620            return Err(f());
621        }
622
623        return Ok(self.data);
624    }
625
626    pub fn unwrap(self) -> u32 {
627        if self == Self::NULL {
628            panic!("NullPointerException");
629        }
630
631        return self.data;
632    }
633
634    pub fn unwrap_or(self, f: u32) -> u32 {
635        if self == Self::NULL {
636            return f;
637        }
638
639        return self.data;
640    }
641
642    pub fn unwrap_or_else<F>(self, f: F) -> u32
643    where
644        F: FnOnce() -> u32,
645    {
646        if self == Self::NULL {
647            return f();
648        }
649
650        return self.data;
651    }
652}
653
654impl Into<u32> for n32 {
655    fn into(self) -> u32 {
656        if self == Self::NULL {
657            panic!("NullPointerException");
658        }
659
660        return self.data;
661    }
662}
663
664impl Into<u32> for &n32 {
665    fn into(self) -> u32 {
666        if self == &n32::NULL {
667            panic!("NullPointerException");
668        }
669
670        return self.data;
671    }
672}
673
674impl Into<usize> for n32 {
675    fn into(self) -> usize {
676        if self == Self::NULL {
677            panic!("NullPointerException");
678        }
679
680        return self.data as usize;
681    }
682}
683
684impl Into<usize> for &n32 {
685    fn into(self) -> usize {
686        if self == &n32::NULL {
687            panic!("NullPointerException");
688        }
689
690        return self.data as usize;
691    }
692}
693
694impl From<u32> for n32 {
695    fn from(data: u32) -> Self {
696        Self::new(data)
697    }
698}
699
700impl From<usize> for n32 {
701    fn from(data: usize) -> Self {
702        Self::new(data as u32)
703    }
704}
705
706impl ops::Add<u32> for n32 {
707    type Output = n32;
708
709    fn add(mut self, rhs: u32) -> n32 {
710        self.data += rhs;
711        if self == Self::NULL {
712            panic!("NullPointerException");
713        }
714        return self;
715    }
716}
717
718impl fmt::Debug for n32 {
719    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
720        if *self == Self::NULL {
721            write!(fmt, "null")
722        } else {
723            write!(fmt, "{}", self.data)
724        }
725    }
726}
727
728impl Serialize for n32 {
729    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
730    where
731        S: Serializer,
732    {
733        if *self == Self::NULL {
734            serializer.serialize_none()
735        } else {
736            serializer.serialize_u32(self.data)
737        }
738    }
739}
740
741pub struct Defer<F: FnOnce()> {
742    f: Option<F>,
743}
744
745impl<F: FnOnce()> Drop for Defer<F> {
746    fn drop(&mut self) {
747        let f = self.f.take().unwrap();
748        f();
749    }
750}
751
752pub fn defer<F: FnOnce()>(f: F) -> Defer<F> {
753    return Defer { f: Some(f) };
754}
755
756#[allow(unused_macros)]
757macro_rules! let_expr {
758    ($left:pat = $right:expr) => {{
759        if let $left = $right {
760            true
761        } else {
762            false
763        }
764    }};
765}
766
767pub struct UnsafeCell<T> {
768    t: T,
769}
770
771impl<T> UnsafeCell<T> {
772    pub const fn new(t: T) -> Self {
773        UnsafeCell { t }
774    }
775
776    pub unsafe fn get_mut(&self) -> &mut T {
777        return &mut *(&self.t as *const T as *mut T);
778    }
779}
780
781unsafe impl<T> Sync for UnsafeCell<T> {}
782unsafe impl<T: Send> Send for UnsafeCell<T> {}
783
784#[repr(C)]
785pub struct IStr {
786    pub len: usize,
787    chars: (),
788}
789
790impl PartialEq for IStr {
791    fn eq(&self, other: &Self) -> bool {
792        return self.as_str() == other.as_str();
793    }
794}
795
796impl fmt::Debug for IStr {
797    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
798        return self.as_str().fmt(fmt);
799    }
800}
801
802impl IStr {
803    pub fn new<'a>(string: &str) -> &'a mut Self {
804        return Self::with_allocator(string, Global);
805    }
806
807    pub fn with_allocator<'a>(string: &str, alloc: impl Allocator) -> &'a mut Self {
808        let (size, align) = (mem::size_of::<usize>(), mem::align_of::<usize>());
809        let layout = unsafe { Layout::from_size_align_unchecked(size + string.len(), align) };
810        let (bytes, string) = (alloc.allocate(layout).unwrap(), string.as_bytes());
811        let (i_str, len) = (bytes.as_ptr(), string.len());
812        let i_str = unsafe { &mut *((&mut (&mut *i_str)[0]) as *mut u8 as *mut IStr) };
813
814        i_str.len = len;
815        unsafe { i_str.as_bytes_mut() }.copy_from_slice(string);
816        return i_str;
817    }
818
819    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
820        let begin = &mut self.chars as *mut () as *mut u8;
821        return slice::from_raw_parts_mut(begin, self.len);
822    }
823
824    pub fn as_str(&self) -> &str {
825        let begin = &self.chars as *const () as *const u8;
826        let slice = unsafe { slice::from_raw_parts(begin, self.len) };
827        return unsafe { str::from_utf8_unchecked(slice) };
828    }
829}
830
831pub trait CloneInto<'a> {
832    type CloneOutput;
833
834    fn clone_into_alloc(&self, alloc: &impl Allocator) -> Self::CloneOutput;
835}
836
837impl<'a, T> CloneInto<'a> for Option<T>
838where
839    T: CloneInto<'a>,
840{
841    type CloneOutput = Option<T::CloneOutput>;
842
843    fn clone_into_alloc(&self, alloc: &impl Allocator) -> Self::CloneOutput {
844        if let Some(a) = self.as_ref() {
845            return Some(a.clone_into_alloc(alloc));
846        }
847
848        return None;
849    }
850}