1use base64::{engine::general_purpose as b64, Engine as _};
5#[cfg(feature = "derive")]
6pub use lazy_borink_derive::UnwrapLazy;
7pub use rmp_serde::decode::Error;
8use serde::de::{self, DeserializeOwned, Visitor};
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10use std::fmt::{self, Debug};
11use std::marker::PhantomData;
12
13#[derive(Clone, PartialEq, Eq)]
92pub struct Lazy<T> {
93 bytes: Option<Vec<u8>>,
94 inner: Option<T>,
95}
96
97impl<T> Debug for Lazy<T>
98where
99 T: Debug,
100{
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 if let Some(inner) = &self.inner {
103 write!(f, "{:?}", inner)?;
104 } else if let Some(bytes) = &self.bytes {
105 f.debug_struct("Lazy").field("bytes", bytes).finish()?;
106 }
107
108 Ok(())
109 }
110}
111
112fn deserialize_lazy<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, Error> {
113 rmp_serde::decode::from_slice(bytes)
114}
115
116fn serialize_lazy<T: Serialize>(inner: &T) -> Vec<u8> {
117 rmp_serde::encode::to_vec_named(inner).unwrap()
118}
119
120impl<T> Lazy<T> {
121 pub fn from_bytes(bytes: Vec<u8>) -> Self {
123 Lazy {
124 bytes: Some(bytes),
125 inner: None,
126 }
127 }
128
129 pub fn from_inner(inner: T) -> Self {
131 Lazy {
132 bytes: None,
133 inner: Some(inner),
134 }
135 }
136
137 pub fn is_deserialized(&self) -> bool {
139 self.inner.is_some()
140 }
141}
142
143impl<T> From<T> for Lazy<T> {
144 fn from(value: T) -> Self {
145 Lazy::from_inner(value)
146 }
147}
148
149impl<T> Lazy<T>
150where
151 T: DeserializeOwned,
152{
153 pub fn try_inner(&mut self) -> Result<&T, Error> {
157 if let Some(bytes) = self.bytes.take() {
158 let inner = deserialize_lazy(&bytes)?;
159 self.inner = Some(inner);
160
161 self.try_inner()
162 } else if let Some(inner) = &self.inner {
163 Ok(inner)
164 } else {
165 panic!("Lazy structure is invalid, it contains no data!")
166 }
167 }
168
169 pub fn try_take(self) -> Result<T, Error> {
171 if let Some(bytes) = self.bytes {
172 deserialize_lazy(&bytes)
173 } else if let Some(inner) = self.inner {
174 Ok(inner)
175 } else {
176 panic!("Lazy structure is invalid, it contains no data!")
177 }
178 }
179
180 pub fn inner(&mut self) -> &T {
182 self.try_inner().unwrap()
183 }
184
185 pub fn take(self) -> T {
187 self.try_take().unwrap()
188 }
189}
190
191impl<T> Lazy<T>
192where
193 T: Serialize,
194{
195 pub fn bytes(&mut self) -> &[u8] {
198 if let Some(inner) = self.inner.take() {
199 let bytes = serialize_lazy(&inner);
200 self.bytes = Some(bytes);
201
202 self.bytes()
203 } else if let Some(bytes) = &self.bytes {
204 bytes
205 } else {
206 panic!("Lazy structure is invalid, it contains no data!")
207 }
208 }
209
210 pub fn take_bytes(self) -> Vec<u8> {
212 if let Some(inner) = self.inner {
213 serialize_lazy(&inner)
214 } else if let Some(bytes) = self.bytes {
215 bytes
216 } else {
217 panic!("Lazy structure is invalid, it contains no data!")
218 }
219 }
220}
221
222impl<'de, T> Deserialize<'de> for Lazy<T>
223where
224 T: DeserializeOwned,
225{
226 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
227 where
228 D: Deserializer<'de>,
229 {
230 struct LazyVisitor<T>
231 where
232 T: DeserializeOwned,
233 {
234 _marker: PhantomData<T>,
235 }
236
237 impl<'de, T> Visitor<'de> for LazyVisitor<T>
238 where
239 T: DeserializeOwned,
240 {
241 type Value = Lazy<T>;
242
243 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
244 formatter.write_str("a byte array or str")
245 }
246
247 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
248 where
249 E: de::Error,
250 {
251 match b64::URL_SAFE_NO_PAD.decode(v) {
252 Ok(data) => Ok(Lazy::from_bytes(data)),
253 Err(_) => Err(E::custom("not valid base64url without padding")),
254 }
255 }
256
257 fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
258 where
259 E: de::Error,
260 {
261 Ok(Lazy::from_bytes(v))
262 }
263
264 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
265 where
266 E: de::Error,
267 {
268 Ok(Lazy::from_bytes(v.to_vec()))
269 }
270 }
271
272 if deserializer.is_human_readable() {
273 deserializer.deserialize_str(LazyVisitor {
274 _marker: PhantomData,
275 })
276 } else {
277 deserializer.deserialize_byte_buf(LazyVisitor {
278 _marker: PhantomData,
279 })
280 }
281 }
282}
283
284impl<T> Serialize for Lazy<T>
285where
286 T: Serialize,
287{
288 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
289 where
290 S: Serializer,
291 {
292 if let Some(data) = &self.bytes {
293 if serializer.is_human_readable() {
294 let s = b64::URL_SAFE_NO_PAD.encode(data);
295 serializer.serialize_str(&s)
296 } else {
297 serializer.serialize_bytes(data)
298 }
299 } else if let Some(inner) = &self.inner {
300 let data = rmp_serde::encode::to_vec_named(inner).unwrap();
301
302 if serializer.is_human_readable() {
303 let s = b64::URL_SAFE_NO_PAD.encode(data);
304 serializer.serialize_str(&s)
305 } else {
306 serializer.serialize_bytes(&data)
307 }
308 } else {
309 panic!("Lazy structure is invalid, it contains no data!")
310 }
311 }
312}
313
314pub trait UnwrapLazy {
340 fn unwrap_lazy(self) -> Self
341 where
342 Self: Sized,
343 {
344 self.try_unwrap_lazy().unwrap()
345 }
346
347 fn try_unwrap_lazy(self) -> Result<Self, Error>
348 where
349 Self: Sized;
350}
351
352impl<T> UnwrapLazy for Lazy<T>
353where
354 T: DeserializeOwned + UnwrapLazy,
355{
356 fn unwrap_lazy(self) -> Self {
357 Self::from_inner(self.take().unwrap_lazy())
358 }
359
360 fn try_unwrap_lazy(self) -> Result<Self, Error> {
361 Ok(Self::from_inner(self.try_take()?))
362 }
363}
364
365impl<'a, T> UnwrapLazy for &'a T
366where
367 T: UnwrapLazy,
368{
369 fn try_unwrap_lazy(self) -> Result<Self, Error> {
370 Ok(self)
371 }
372}
373
374impl<'a, T> UnwrapLazy for &'a mut T
375where
376 T: UnwrapLazy,
377{
378 fn try_unwrap_lazy(self) -> Result<Self, Error> {
379 Ok(self)
380 }
381}
382
383impl<'a, T> UnwrapLazy for &'a [T]
384where
385 T: UnwrapLazy,
386{
387 fn try_unwrap_lazy(self) -> Result<Self, Error> {
388 Ok(self)
389 }
390}
391
392impl<'a, T> UnwrapLazy for &'a mut [T]
393where
394 T: UnwrapLazy,
395{
396 fn try_unwrap_lazy(self) -> Result<Self, Error> {
397 Ok(self)
398 }
399}
400
401impl<T> UnwrapLazy for Vec<T>
402where
403 T: UnwrapLazy,
404{
405 fn try_unwrap_lazy(self) -> Result<Self, Error> {
406 Ok(self)
407 }
408}
409
410impl<T> UnwrapLazy for Box<T>
411where
412 T: UnwrapLazy,
413{
414 fn try_unwrap_lazy(self) -> Result<Self, Error> {
415 Ok(self)
416 }
417}
418
419macro_rules! impl_unwrap_lazy_for_primitives {
420 ($($t:ty),*) => {
421 $(
422 impl UnwrapLazy for $t {
423 fn try_unwrap_lazy(self) -> Result<Self, Error> {
424 Ok(self)
425 }
426 }
427 )*
428 };
429}
430
431impl_unwrap_lazy_for_primitives!(
432 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64, bool, char, String
433);
434
435#[cfg(test)]
436mod test {
437 use super::*;
438
439 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, UnwrapLazy)]
441 struct Claims {
442 my_claim: String,
443 }
444
445 #[derive(Deserialize, Serialize, Debug, Clone, PartialEq, UnwrapLazy)]
446 struct User {
447 user_id: String,
448 password_file: String,
449 claims: Lazy<Claims>,
450 }
451
452 #[derive(Deserialize, Serialize, Debug, PartialEq, UnwrapLazy)]
453 struct UserMeta {
454 user: User,
455 }
456
457 #[test]
458 fn lazy_unwrap() {
459 let claims = Claims {
460 my_claim: "hi".to_owned(),
461 };
462
463 let lazy_claims = Lazy::from_inner(claims.clone());
464 let user = User {
465 user_id: "abc".to_owned(),
466 password_file: "hi".to_owned(),
467 claims: lazy_claims,
468 };
469
470 assert_eq!(
471 user.claims,
472 Lazy {
473 inner: Some(claims.clone()),
474 bytes: None
475 }
476 );
477 let user_json = serde_json::to_string(&user).unwrap();
480
481 assert_eq!(
482 user_json,
483 "{\"user_id\":\"abc\",\"password_file\":\"hi\",\"claims\":\"gahteV9jbGFpbaJoaQ\"}"
484 );
485 let claims_bytes = serialize_lazy(&claims);
488 let user: User = serde_json::from_str(&user_json).unwrap();
489 assert_eq!(
490 user.claims,
491 Lazy {
492 inner: None,
493 bytes: Some(claims_bytes.clone())
494 }
495 );
496 assert_eq!(
499 user.clone().claims.unwrap_lazy(),
500 Lazy {
501 inner: Some(claims.clone()),
502 bytes: None
503 }
504 );
505 assert_eq!(user.clone().claims.take(), claims);
506 let mut user_mut = user.clone();
507 assert_eq!(user_mut.claims.inner(), &claims);
508 assert_eq!(
509 user_mut.claims,
510 Lazy {
511 inner: Some(claims.clone()),
512 bytes: None
513 }
514 );
515
516 let user_m = UserMeta { user };
517 assert_eq!(
518 user_m.user.claims,
519 Lazy {
520 inner: None,
521 bytes: Some(claims_bytes.clone())
522 }
523 );
524
525 let user_m = user_m.unwrap_lazy();
526 assert_eq!(
527 user_m.user.unwrap_lazy().claims,
528 Lazy {
529 inner: Some(claims.clone()),
530 bytes: None
531 }
532 );
533
534 }
536
537 #[test]
538 fn lazy_trait() {
539 let claims = Claims {
540 my_claim: "hi".to_owned(),
541 };
542 let claims_bytes = serialize_lazy(&claims);
543 let lazy_claims: Lazy<Claims> = claims.clone().into();
544 assert_eq!(
545 lazy_claims,
546 Lazy {
547 inner: Some(claims.clone()),
548 bytes: None
549 }
550 );
551 let mut lazy_mut = lazy_claims.clone();
552 assert_eq!(claims_bytes, lazy_mut.bytes());
553 assert_eq!(
554 lazy_mut,
555 Lazy {
556 inner: None,
557 bytes: Some(claims_bytes.clone())
558 }
559 );
560 assert_eq!(claims_bytes, lazy_claims.clone().take_bytes());
561 let lazy_serial = lazy_mut.clone();
562 assert_eq!(&claims, lazy_mut.inner());
563 assert_eq!(
564 lazy_mut,
565 Lazy {
566 inner: Some(claims.clone()),
567 bytes: None
568 }
569 );
570 assert_eq!(claims, lazy_serial.take());
571 }
572
573 #[test]
574 fn msgpack_round_trip() {
575 let claims = Claims {
576 my_claim: "hi".to_owned(),
577 };
578 let claims_bytes = serialize_lazy(&claims);
579 let lazy_claims = Lazy::from(claims.clone());
580 let user = User {
581 user_id: "abc".to_owned(),
582 password_file: "hi".to_owned(),
583 claims: lazy_claims,
584 };
585
586 let user_lazy = User {
587 user_id: "abc".to_owned(),
588 password_file: "hi".to_owned(),
589 claims: Lazy::from_bytes(claims_bytes),
590 };
591
592 let bytes = rmp_serde::encode::to_vec_named(&user).unwrap();
593
594 let decoded: User = rmp_serde::decode::from_slice(&bytes).unwrap();
595
596 assert_eq!(user_lazy, decoded);
597 assert_eq!(user, decoded.unwrap_lazy())
598 }
599}