1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(all(not(feature = "std"), feature = "alloc"))]
4extern crate alloc;
5
6use core::{ops::Deref, pin::Pin};
7
8pub use boxed::BoxLazy;
9pub use decode_cursor::DecodeCursor;
10pub use encode_cursor::EncodeCursor;
11pub use list::{ListGen, ListLazy};
12
13mod boxed;
14mod copy_primitives;
15mod decode_cursor;
16mod encode_cursor;
17mod list;
18mod option;
19mod result;
20mod string;
21#[cfg(test)]
22mod tests;
23
24pub trait BaseLen {
25 const BASE_LEN: usize;
26}
27
28pub trait Encode: BaseLen {
29 fn scratch_len(&self) -> usize;
30
31 fn encode(&self, cursor: &mut EncodeCursor);
32}
33
34#[derive(Debug)]
35pub struct DecodeError;
36
37impl core::fmt::Display for DecodeError {
38 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39 write!(f, "failed to decode mproto value")
40 }
41}
42
43impl core::error::Error for DecodeError {}
44
45pub type DecodeResult<T> = Result<T, DecodeError>;
46
47pub trait Decode<'a>: BaseLen + Sized {
48 fn decode(cursor: &DecodeCursor<'a>) -> DecodeResult<Self>;
49}
50
51pub trait Compatible<Other: ?Sized>: Encode {}
52
53pub trait Owned: Encode + for<'a> Decode<'a> + Compatible<Self> + Clone + Send + Sync + 'static {
54 type Lazy<'a>: Lazy<'a, Owned = Self>;
55
56 fn lazy_to_owned(lazy: Self::Lazy<'_>) -> DecodeResult<Self>;
57}
58
59pub trait Lazy<'a>: Encode + Decode<'a> + Copy + Clone + PartialEq + core::fmt::Debug {
60 type Owned: Owned<Lazy<'a> = Self>;
61}
62
63#[inline]
64pub fn encoded_len<T: Encode>(value: T) -> usize {
65 T::BASE_LEN + value.scratch_len()
66}
67
68#[inline]
69pub fn encode_value<E: Encode>(v: E, mut buf: impl AsMut<[u8]>) -> usize {
70 let mut cursor = EncodeCursor::new::<E>(buf.as_mut());
71 v.encode(&mut cursor);
72 cursor.encoded_len()
73}
74
75#[cfg(any(feature = "std", feature = "alloc"))]
76#[inline]
77pub fn encode_value_vec<E: Encode>(v: E) -> Vec<u8> {
78 let mut buf = vec![0u8; encoded_len(&v)];
79 let mut cursor = EncodeCursor::new::<E>(buf.as_mut());
80 v.encode(&mut cursor);
81 buf
82}
83
84#[inline]
85pub fn decode_value<'a, D: Decode<'a>>(buf: &'a [u8]) -> DecodeResult<D> {
86 Decode::decode(&DecodeCursor::new(buf))
87}
88
89pub struct LazyBuf<T: Owned, B> {
91 buf: Pin<B>,
92 lazy: T::Lazy<'static>,
93}
94
95mod sealed {
96 pub trait LazyBufMapFn<T, U>: FnOnce(T) -> U {}
99 impl<F, T, U> LazyBufMapFn<T, U> for F where F: FnOnce(T) -> U {}
100}
101
102impl<T: Owned, B: Deref<Target = [u8]> + core::marker::Unpin> LazyBuf<T, B> {
103 #[inline]
104 pub fn new(buf: B) -> Self {
105 let buf = Pin::new(buf);
106 let lazy: T::Lazy<'_> = decode_value(buf.as_ref().get_ref().as_ref()).unwrap();
107 let lazy = unsafe { core::mem::transmute(lazy) };
110 Self { buf, lazy }
111 }
112
113 #[inline]
114 pub fn get<'a>(&'a self) -> T::Lazy<'a> {
115 unsafe { core::mem::transmute(self.lazy.clone()) }
117 }
118
119 #[inline]
120 pub fn map<U: Owned, F>(self, f: F) -> LazyBuf<U, B>
121 where
122 F: for<'a> sealed::LazyBufMapFn<T::Lazy<'a>, U::Lazy<'a>>,
123 {
124 let lazy = f(self.lazy);
125 let lazy = unsafe { core::mem::transmute(lazy) };
128 LazyBuf {
129 buf: self.buf,
130 lazy,
131 }
132 }
133}
134
135impl<T, U: Compatible<T> + ?Sized> Compatible<T> for &U {}
136
137impl<T: BaseLen + ?Sized> BaseLen for &T {
138 const BASE_LEN: usize = T::BASE_LEN;
139}
140
141impl<T: Encode + ?Sized> Encode for &T {
142 #[inline]
143 fn scratch_len(&self) -> usize {
144 T::scratch_len(self)
145 }
146
147 #[inline]
148 fn encode(&self, cursor: &mut EncodeCursor) {
149 T::encode(self, cursor);
150 }
151}
152
153impl<T: BaseLen + ?Sized> BaseLen for &mut T {
154 const BASE_LEN: usize = T::BASE_LEN;
155}
156
157impl<T: Encode + ?Sized> Encode for &mut T {
158 #[inline]
159 fn scratch_len(&self) -> usize {
160 T::scratch_len(self)
161 }
162
163 #[inline]
164 fn encode(&self, cursor: &mut EncodeCursor) {
165 T::encode(self, cursor);
166 }
167}
168
169pub const fn max(a: usize, b: usize) -> usize {
170 [a, b][(a < b) as usize]
171}