1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{Data, DataStruct, DeriveInput, Fields, parse_macro_input};
4
5#[proc_macro_derive(Bytes)]
45pub fn derive_bytes(input: TokenStream) -> TokenStream {
46 let input = parse_macro_input!(input as DeriveInput);
47 let struct_name = &input.ident;
48 let generics = &input.generics;
49 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
50
51 let inner_type = match &input.data {
52 Data::Struct(DataStruct {
53 fields: Fields::Unnamed(fields),
54 ..
55 }) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
56 _ => {
57 return syn::Error::new_spanned(
58 &input.ident,
59 "Bytes can only be derived for single-field tuple structs",
60 )
61 .to_compile_error()
62 .into();
63 }
64 };
65
66 let has_generics = !generics.params.is_empty();
68
69 let expanded = if has_generics {
70 let where_clause = if where_clause.is_some() {
71 quote! { #where_clause #inner_type: ::vecdb::Bytes, }
72 } else {
73 quote! { where #inner_type: ::vecdb::Bytes, }
74 };
75
76 quote! {
77 impl #impl_generics ::vecdb::Bytes for #struct_name #ty_generics #where_clause {
78 type Array = <#inner_type as ::vecdb::Bytes>::Array;
79 const IS_NATIVE_LAYOUT: bool =
80 <#inner_type as ::vecdb::Bytes>::IS_NATIVE_LAYOUT
81 && ::core::mem::size_of::<Self>() == ::core::mem::size_of::<#inner_type>()
82 && ::core::mem::align_of::<Self>() == ::core::mem::align_of::<#inner_type>();
83
84 fn to_bytes(&self) -> Self::Array {
85 self.0.to_bytes()
86 }
87
88 fn from_bytes(bytes: &[u8]) -> ::vecdb::Result<Self> {
89 Ok(Self(<#inner_type>::from_bytes(bytes)?))
90 }
91 }
92 }
93 } else {
94 quote! {
95 impl ::vecdb::Bytes for #struct_name {
96 type Array = <#inner_type as ::vecdb::Bytes>::Array;
97 const IS_NATIVE_LAYOUT: bool =
98 <#inner_type as ::vecdb::Bytes>::IS_NATIVE_LAYOUT
99 && ::core::mem::size_of::<Self>() == ::core::mem::size_of::<#inner_type>()
100 && ::core::mem::align_of::<Self>() == ::core::mem::align_of::<#inner_type>();
101
102 fn to_bytes(&self) -> Self::Array {
103 self.0.to_bytes()
104 }
105
106 fn from_bytes(bytes: &[u8]) -> ::vecdb::Result<Self> {
107 Ok(Self(<#inner_type>::from_bytes(bytes)?))
108 }
109 }
110 }
111 };
112
113 TokenStream::from(expanded)
114}
115
116#[proc_macro_derive(Pco)]
167pub fn derive_pco(input: TokenStream) -> TokenStream {
168 let input = parse_macro_input!(input as DeriveInput);
169 let struct_name = &input.ident;
170 let generics = &input.generics;
171 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
172
173 let inner_type = match &input.data {
174 Data::Struct(DataStruct {
175 fields: Fields::Unnamed(fields),
176 ..
177 }) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
178 _ => {
179 return syn::Error::new_spanned(
180 &input.ident,
181 "Pco can only be derived for single-field tuple structs",
182 )
183 .to_compile_error()
184 .into();
185 }
186 };
187
188 let has_generics = !generics.params.is_empty();
190
191 let expanded = if has_generics {
192 let where_clause = if where_clause.is_some() {
196 quote! { #where_clause #inner_type: ::vecdb::Pco + ::vecdb::Bytes, }
197 } else {
198 quote! { where #inner_type: ::vecdb::Pco + ::vecdb::Bytes, }
199 };
200
201 quote! {
202 impl #impl_generics ::vecdb::Bytes for #struct_name #ty_generics #where_clause {
203 type Array = <#inner_type as ::vecdb::Bytes>::Array;
204 const IS_NATIVE_LAYOUT: bool =
205 <#inner_type as ::vecdb::Bytes>::IS_NATIVE_LAYOUT
206 && ::core::mem::size_of::<Self>() == ::core::mem::size_of::<#inner_type>()
207 && ::core::mem::align_of::<Self>() == ::core::mem::align_of::<#inner_type>();
208
209 fn to_bytes(&self) -> Self::Array {
210 self.0.to_bytes()
211 }
212
213 fn from_bytes(bytes: &[u8]) -> ::vecdb::Result<Self> {
214 Ok(Self(<#inner_type>::from_bytes(bytes)?))
215 }
216 }
217
218 impl #impl_generics ::vecdb::TransparentPco<<#inner_type as ::vecdb::Pco>::NumberType> for #struct_name #ty_generics #where_clause {}
219
220 impl #impl_generics ::vecdb::Pco for #struct_name #ty_generics #where_clause {
221 type NumberType = <#inner_type as ::vecdb::Pco>::NumberType;
222 }
223 }
224 } else {
225 quote! {
226 impl ::vecdb::Bytes for #struct_name {
227 type Array = <#inner_type as ::vecdb::Bytes>::Array;
228 const IS_NATIVE_LAYOUT: bool =
229 <#inner_type as ::vecdb::Bytes>::IS_NATIVE_LAYOUT
230 && ::core::mem::size_of::<Self>() == ::core::mem::size_of::<#inner_type>()
231 && ::core::mem::align_of::<Self>() == ::core::mem::align_of::<#inner_type>();
232
233 fn to_bytes(&self) -> Self::Array {
234 self.0.to_bytes()
235 }
236
237 fn from_bytes(bytes: &[u8]) -> ::vecdb::Result<Self> {
238 Ok(Self(<#inner_type>::from_bytes(bytes)?))
239 }
240 }
241
242 impl ::vecdb::TransparentPco<<#inner_type as ::vecdb::Pco>::NumberType> for #struct_name {}
243
244 impl ::vecdb::Pco for #struct_name {
245 type NumberType = <#inner_type as ::vecdb::Pco>::NumberType;
246 }
247 }
248 };
249
250 TokenStream::from(expanded)
251}