lazy.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. use crate::{AnchorDeserialize, Pubkey};
  2. /// A helper trait to make lazy deserialization work.
  3. ///
  4. /// Currently this is only implemented for [`borsh`], as it's not necessary for zero copy via
  5. /// [`bytemuck`]. However, the functionality can be extended when we support custom serialization
  6. /// in the future.
  7. ///
  8. /// # Note
  9. ///
  10. /// You should avoid implementing this trait manually.
  11. ///
  12. /// It's currently implemented automatically if you derive [`AnchorDeserialize`]:
  13. ///
  14. /// ```ignore
  15. /// #[derive(AnchorDeserialize)]
  16. /// pub struct MyStruct {
  17. /// field: u8,
  18. /// }
  19. /// ```
  20. pub trait Lazy: AnchorDeserialize {
  21. /// Get the serialized size of the type from the given buffer.
  22. ///
  23. /// For performance reasons, this method does not verify the validity of the data, and should
  24. /// never fail.
  25. ///
  26. /// # Panics
  27. ///
  28. /// If the given buffer cannot be used to deserialize the data e.g. it's shorter than the
  29. /// expected data. However, this doesn't mean it will panic **whenever** there is an incorrect
  30. /// data e.g. passing **any** data for `bool::size_of` works, even when the buffer is empty.
  31. fn size_of(buf: &[u8]) -> usize;
  32. }
  33. macro_rules! impl_sized {
  34. ($ty: ty) => {
  35. impl Lazy for $ty {
  36. #[inline(always)]
  37. fn size_of(_buf: &[u8]) -> usize {
  38. ::core::mem::size_of::<$ty>()
  39. }
  40. }
  41. };
  42. }
  43. impl_sized!(bool);
  44. impl_sized!(u8);
  45. impl_sized!(u16);
  46. impl_sized!(u32);
  47. impl_sized!(u64);
  48. impl_sized!(u128);
  49. impl_sized!(i8);
  50. impl_sized!(i16);
  51. impl_sized!(i32);
  52. impl_sized!(i64);
  53. impl_sized!(i128);
  54. impl_sized!(f32);
  55. impl_sized!(f64);
  56. impl_sized!(Pubkey);
  57. impl<T: Lazy, const N: usize> Lazy for [T; N] {
  58. #[inline(always)]
  59. fn size_of(buf: &[u8]) -> usize {
  60. N * T::size_of(buf)
  61. }
  62. }
  63. impl Lazy for String {
  64. #[inline(always)]
  65. fn size_of(buf: &[u8]) -> usize {
  66. LEN + get_len(buf)
  67. }
  68. }
  69. impl<T: Lazy> Lazy for Option<T> {
  70. #[inline(always)]
  71. fn size_of(buf: &[u8]) -> usize {
  72. 1 + match buf.first() {
  73. Some(0) => 0,
  74. Some(1) => T::size_of(&buf[1..]),
  75. _ => unreachable!(),
  76. }
  77. }
  78. }
  79. impl<T: Lazy> Lazy for Vec<T> {
  80. #[inline(always)]
  81. fn size_of(buf: &[u8]) -> usize {
  82. (0..get_len(buf)).fold(LEN, |acc, _| acc + T::size_of(&buf[acc..]))
  83. }
  84. }
  85. /// `borsh` length identifier of unsized types.
  86. const LEN: usize = 4;
  87. #[inline(always)]
  88. fn get_len(buf: &[u8]) -> usize {
  89. u32::from_le_bytes((buf[..LEN].try_into()).unwrap())
  90. .try_into()
  91. .unwrap()
  92. }
  93. #[cfg(test)]
  94. mod tests {
  95. use super::*;
  96. use crate::AnchorSerialize;
  97. macro_rules! len {
  98. ($val: expr) => {
  99. $val.try_to_vec().unwrap().len()
  100. };
  101. }
  102. #[test]
  103. fn sized() {
  104. // Sized inputs don't care about the passed data
  105. const EMPTY: &[u8] = &[];
  106. assert_eq!(bool::size_of(EMPTY), len!(true));
  107. assert_eq!(u8::size_of(EMPTY), len!(0u8));
  108. assert_eq!(u16::size_of(EMPTY), len!(0u16));
  109. assert_eq!(u32::size_of(EMPTY), len!(0u32));
  110. assert_eq!(u64::size_of(EMPTY), len!(0u64));
  111. assert_eq!(u128::size_of(EMPTY), len!(0u128));
  112. assert_eq!(i8::size_of(EMPTY), len!(0i8));
  113. assert_eq!(i16::size_of(EMPTY), len!(0i16));
  114. assert_eq!(i32::size_of(EMPTY), len!(0i32));
  115. assert_eq!(i64::size_of(EMPTY), len!(0i64));
  116. assert_eq!(i128::size_of(EMPTY), len!(0i128));
  117. assert_eq!(f32::size_of(EMPTY), len!(0f32));
  118. assert_eq!(f64::size_of(EMPTY), len!(0f64));
  119. assert_eq!(Pubkey::size_of(EMPTY), len!(Pubkey::default()));
  120. assert_eq!(<[i32; 4]>::size_of(EMPTY), len!([0i32; 4]));
  121. }
  122. #[test]
  123. fn r#unsized() {
  124. assert_eq!(String::size_of(&[1, 0, 0, 0, 65]), len!(String::from("a")));
  125. assert_eq!(<Option<u8>>::size_of(&[0]), len!(Option::<u8>::None));
  126. assert_eq!(<Option<u8>>::size_of(&[1, 1]), len!(Some(1u8)));
  127. assert_eq!(<Vec<u8>>::size_of(&[1, 0, 0, 0, 1]), len!(vec![1u8]));
  128. assert_eq!(
  129. <Vec<String>>::size_of(&[1, 0, 0, 0, 1, 0, 0, 0, 65]),
  130. len!(vec![String::from("a")])
  131. );
  132. assert_eq!(
  133. <Vec<String>>::size_of(&[2, 0, 0, 0, 1, 0, 0, 0, 65, 2, 0, 0, 0, 65, 66]),
  134. len!(vec![String::from("a"), String::from("ab")])
  135. );
  136. }
  137. #[test]
  138. fn defined() {
  139. // Struct
  140. #[derive(AnchorSerialize, AnchorDeserialize)]
  141. struct MyStruct {
  142. a: u8,
  143. b: Vec<u8>,
  144. c: Option<String>,
  145. }
  146. assert_eq!(
  147. MyStruct::size_of(&[1, 2, 0, 0, 0, 1, 2, 1, 1, 0, 0, 0, 65]),
  148. len!(MyStruct {
  149. a: 1,
  150. b: vec![1u8, 2],
  151. c: Some(String::from("a"))
  152. })
  153. );
  154. // Enum
  155. #[derive(AnchorSerialize, AnchorDeserialize)]
  156. enum MyEnum {
  157. Unit,
  158. Named { a: u8 },
  159. Unnamed(i16, i16),
  160. }
  161. assert_eq!(MyEnum::size_of(&[0]), len!(MyEnum::Unit));
  162. assert_eq!(MyEnum::size_of(&[1, 23]), len!(MyEnum::Named { a: 1 }));
  163. assert_eq!(
  164. MyEnum::size_of(&[2, 1, 2, 1, 2]),
  165. len!(MyEnum::Unnamed(1, 2))
  166. );
  167. }
  168. #[test]
  169. fn generic() {
  170. #[derive(AnchorSerialize, AnchorDeserialize)]
  171. struct GenericStruct<T: Lazy> {
  172. t: T,
  173. }
  174. assert_eq!(
  175. GenericStruct::<i64>::size_of(&[1, 2, 3, 4, 5, 6, 7, 8]),
  176. len!(GenericStruct { t: 1i64 })
  177. );
  178. assert_eq!(
  179. GenericStruct::<Vec<u8>>::size_of(&[8, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]),
  180. len!(GenericStruct { t: vec![0u8; 8] })
  181. );
  182. }
  183. }