Skip to main content

libutils_log/
mod.rs

1//^
2//^ HEAD
3//^
4
5//> HEAD -> NO_STD
6#![no_std]
7
8//> HEAD -> FEATURES
9#![feature(allocator_api)]
10#![feature(const_trait_impl)]
11#![feature(const_destruct)]
12#![feature(const_cmp)]
13#![feature(const_default)]
14#![feature(const_heap)]
15#![feature(const_convert)]
16#![feature(const_slice_make_iter)]
17#![feature(const_iter)]
18#![feature(test)]
19#![feature(const_result_trait_fn)]
20#![feature(const_result_unwrap_unchecked)]
21
22//> HEAD -> CRATES
23extern crate alloc;
24extern crate test;
25
26//> HEAD -> MODULES
27#[cfg(test)]
28mod benches;
29mod conversions;
30mod iterators;
31mod references;
32#[cfg(test)]
33mod tests;
34
35//> HEAD -> CORE
36use core::{
37    fmt::{
38        Debug,
39        Formatter,
40        Result as Format
41    },
42    alloc::{
43        Allocator,
44        Layout
45    },
46    slice::Iter,
47    marker::Destruct
48};
49
50//> HEAD -> ALLOC
51use alloc::alloc::Global;
52
53//> HEAD -> POINTER
54use libutils_pointer::Pointer;
55
56
57//^
58//^ LOG
59//^
60
61//> LOG -> STRUCT
62#[derive(Clone)]
63pub struct Log<Type> {
64    pointer: Pointer<Type>,
65    length: usize,
66    capacity: usize
67}
68
69//> LOG -> IMPLEMENTATION
70impl<Type> Log<Type> {
71    #[inline]
72    const fn grow(&mut self) -> () {
73        self.pointer = match self.pointer.take() {
74            None => Global.allocate(Layout::from_size_align(size_of::<Type>(), align_of::<Type>()).ok().unwrap()),
75            Some(pointer) => unsafe {Global.grow(
76                pointer.cast(), 
77                Layout::from_size_align(self.capacity * size_of::<Type>(), align_of::<Type>()).ok().unwrap(), 
78                Layout::from_size_align(self.capacity * 2 * size_of::<Type>(), align_of::<Type>()).ok().unwrap()
79            )}
80        }.ok().unwrap().cast().into();
81        self.capacity = (self.capacity * 2).max(1);
82    }
83    #[inline]
84    pub const fn new() -> Self {return Self::default()}
85    #[inline]
86    pub const fn len(&self) -> usize {return self.length}
87    #[inline]
88    pub const fn is_empty(&self) -> bool {return self.length == 0}
89    #[inline]
90    pub const fn iter<'valid>(&'valid self) -> Iter<'valid, Type> {return self.as_ref().iter()}
91}
92
93//> LOG -> CONST DESTRUCT IMPLEMENTATION
94const impl<Type: [const] Destruct> Log<Type> {
95    #[inline]
96    pub fn push(&mut self, value: Type) -> () {
97        if self.length == self.capacity {self.grow()}
98        unsafe {self.pointer.add(self.length).write(value)};
99        self.length += 1;
100    }
101}
102
103//> LOG -> DEFAULT
104const impl<Type> Default for Log<Type> {
105    fn default() -> Self {return Self {
106        pointer: Pointer::default(),
107        length: 0,
108        capacity: 0
109    }}
110}
111
112//> LOG -> EXTEND
113impl<Type> Extend<Type> for Log<Type> {
114    #[inline]
115    fn extend<T: IntoIterator<Item = Type>>(&mut self, iter: T) {iter.into_iter().for_each(|item| self.push(item))}
116}
117
118//> LOG -> DEBUG
119impl<Type: Debug> Debug for Log<Type> {
120    fn fmt(&self, formatter: &mut Formatter<'_>) -> Format {Debug::fmt(self.as_ref(), formatter)}
121}
122
123//> LOG -> DROP
124impl<Type> Drop for Log<Type> {
125    fn drop(&mut self) {if let Some(pointer) = self.pointer.take() {
126        for index in 0..self.length {drop(unsafe {pointer.add(index).read()})}
127        unsafe {Global.deallocate(pointer.cast(), Layout::from_size_align(self.capacity * size_of::<Type>(), align_of::<Type>()).unwrap());}
128    }}
129}