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