rapira/
lib.rs

1// #![feature(trace_macros)]
2// #![feature(log_syntax)]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5mod allocated;
6pub mod error;
7mod from_u8;
8pub mod funcs;
9mod implements;
10#[cfg(feature = "std")]
11mod macros;
12pub mod max_cap;
13mod primitive;
14
15pub use error::{RapiraError, Result};
16pub use from_u8::{EnumFromU8Error, FromU8};
17#[cfg(feature = "postcard")]
18pub use implements::postcard;
19#[cfg(feature = "zerocopy")]
20pub use implements::zero;
21pub use primitive::{byte_rapira, bytes_rapira, str_rapira};
22
23#[cfg(feature = "alloc")]
24extern crate alloc;
25
26pub use funcs::{check_bytes, deser_unchecked, deser_unsafe, deserialize, size};
27#[cfg(feature = "alloc")]
28pub use funcs::{extend_vec, serialize};
29pub use rapira_derive::{FromU8, PrimitiveFromEnum, Rapira};
30
31pub trait Rapira {
32    const STATIC_SIZE: Option<usize> = None;
33    const MIN_SIZE: usize;
34
35    /// size of bytes for serialize
36    fn size(&self) -> usize;
37
38    /// check bytes, collections len, check utf-8, NonZero, f32 and others...
39    fn check_bytes(slice: &mut &[u8]) -> Result<()>;
40
41    /// this is safe, but not check collections capacity!
42    /// recommend use only for safe data (example: from DB), not external data.
43    fn from_slice(slice: &mut &[u8]) -> Result<Self>
44    where
45        Self: Sized;
46
47    #[inline]
48    fn debug_from_slice(slice: &mut &[u8]) -> Result<Self>
49    where
50        Self: Sized + std::fmt::Debug,
51    {
52        let len = slice.len();
53        Self::from_slice(slice)
54            .inspect(|item| {
55                println!("len: {len}, item: {item:?}");
56            })
57            .inspect_err(|err| {
58                println!("len: {len}, err: {err:?}");
59            })
60    }
61
62    /// # Safety
63    ///
64    /// this mean not unsafe, but unchecked
65    /// utf-8 strings, NonZero, float numbers not check
66    #[inline]
67    unsafe fn from_slice_unchecked(slice: &mut &[u8]) -> Result<Self>
68    where
69        Self: Sized,
70    {
71        Self::from_slice(slice)
72    }
73
74    /// # Safety
75    ///
76    /// This is unsafe, but maybe safe after check_bytes fn
77    unsafe fn from_slice_unsafe(slice: &mut &[u8]) -> Result<Self>
78    where
79        Self: Sized,
80    {
81        Self::from_slice(slice)
82    }
83
84    #[inline]
85    fn try_convert_to_bytes(&self, slice: &mut [u8], cursor: &mut usize) -> Result<()> {
86        self.convert_to_bytes(slice, cursor);
87        Ok(())
88    }
89
90    fn convert_to_bytes(&self, slice: &mut [u8], cursor: &mut usize);
91}
92
93pub const LEN_SIZE: usize = 4;
94
95#[inline]
96pub fn push(slice: &mut [u8], cursor: &mut usize, item: u8) {
97    let s = slice.get_mut(*cursor).unwrap();
98    *s = item;
99    *cursor += 1;
100}
101
102#[inline]
103pub fn try_push(slice: &mut [u8], cursor: &mut usize, item: u8) -> Result<()> {
104    let s = slice.get_mut(*cursor).ok_or(RapiraError::SliceLen)?;
105    *s = item;
106    *cursor += 1;
107
108    Ok(())
109}
110
111#[inline]
112pub fn extend(slice: &mut [u8], cursor: &mut usize, items: &[u8]) {
113    let end = *cursor + items.len();
114    let s = slice.get_mut(*cursor..end).unwrap();
115    s.copy_from_slice(items);
116    *cursor = end;
117}
118
119#[inline]
120pub fn try_extend(slice: &mut [u8], cursor: &mut usize, items: &[u8]) -> Result<()> {
121    let end = *cursor + items.len();
122    let s = slice.get_mut(*cursor..end).ok_or(RapiraError::SliceLen)?;
123    s.copy_from_slice(items);
124    *cursor = end;
125
126    Ok(())
127}
128
129pub const fn static_size<const N: usize>(arr: [Option<usize>; N]) -> Option<usize> {
130    let mut i = 0;
131    let mut size = 0;
132    while i < arr.len() {
133        let item = arr[i];
134        match item {
135            Some(s) => {
136                size += s;
137            }
138            None => {
139                return None;
140            }
141        }
142        i += 1;
143    }
144    Some(size)
145}
146
147pub const fn enum_size<const N: usize>(arr: [Option<usize>; N]) -> Option<usize> {
148    let mut i = 0;
149    let mut size = 0;
150    let mut is_init = false;
151    while i < arr.len() {
152        let item = arr[i];
153        match item {
154            Some(s) => {
155                if !is_init {
156                    size = s;
157                    is_init = true;
158                } else if s != size {
159                    return None;
160                }
161            }
162            None => {
163                return None;
164            }
165        }
166        i += 1;
167    }
168    Some(size + 1)
169}
170
171pub const fn min_size(arr: &'static [usize]) -> usize {
172    let mut i = 0;
173    let mut size = 0;
174    while i < arr.len() {
175        let item = arr[i];
176        size += item;
177        i += 1;
178    }
179    size
180}
181
182pub const fn enum_min_size(arr: &'static [usize]) -> usize {
183    let mut i = 0;
184    let mut size = 0;
185    let mut is_init = false;
186    while i < arr.len() {
187        let item = arr[i];
188        if !is_init {
189            size = item;
190            is_init = true;
191        } else if size < item {
192            size = item;
193        }
194        i += 1;
195    }
196    size + 1
197}