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