1use crate::utils::{self, FieldInfo};
6use proc_macro2::Span;
7use proc_macro2::TokenStream as TokenStream2;
8use quote::{quote, ToTokens};
9use syn::spanned::Spanned;
10use syn::{
11 parse_quote, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident, Lifetime,
12 PathArguments, Type, TypePath,
13};
14
15pub fn make_varule_impl(ule_name: Ident, mut input: DeriveInput) -> TokenStream2 {
16 if input.generics.type_params().next().is_some()
17 || input.generics.const_params().next().is_some()
18 || input.generics.lifetimes().count() > 1
19 {
20 return Error::new(
21 input.generics.span(),
22 "#[make_varule] must be applied to a struct without any type or const parameters and at most one lifetime",
23 )
24 .to_compile_error();
25 }
26
27 let sp = input.span();
28 let attrs = match utils::extract_attributes_common(&mut input.attrs, sp, true) {
29 Ok(val) => val,
30 Err(e) => return e.to_compile_error(),
31 };
32
33 let lt = input.generics.lifetimes().next();
34
35 if let Some(lt) = lt {
36 if lt.colon_token.is_some() || !lt.bounds.is_empty() {
37 return Error::new(
38 input.generics.span(),
39 "#[make_varule] must be applied to a struct without lifetime bounds",
40 )
41 .to_compile_error();
42 }
43 }
44
45 let lt = lt.map(|l| &l.lifetime);
46
47 let name = &input.ident;
48 let input_span = input.span();
49
50 let fields = match input.data {
51 Data::Struct(ref mut s) => &mut s.fields,
52 _ => {
53 return Error::new(input.span(), "#[make_varule] must be applied to a struct")
54 .to_compile_error();
55 }
56 };
57
58 if fields.is_empty() {
59 return Error::new(
60 input.span(),
61 "#[make_varule] must be applied to a struct with at least one field",
62 )
63 .to_compile_error();
64 }
65
66 let mut sized_fields = vec![];
67 let mut unsized_fields = vec![];
68
69 let mut custom_varule_idents = vec![];
70
71 for field in fields.iter_mut() {
72 match utils::extract_field_attributes(&mut field.attrs) {
73 Ok(i) => custom_varule_idents.push(i),
74 Err(e) => return e.to_compile_error(),
75 }
76 }
77
78 for (i, field) in fields.iter().enumerate() {
79 match UnsizedField::new(field, i, custom_varule_idents[i].clone()) {
80 Ok(o) => unsized_fields.push(o),
81 Err(_) => sized_fields.push(FieldInfo::new_for_field(field, i)),
82 }
83 }
84
85 if unsized_fields.is_empty() {
86 let last_field_index = fields.len() - 1;
87 let last_field = fields.iter().next_back().unwrap();
88
89 let e = UnsizedField::new(
90 last_field,
91 last_field_index,
92 custom_varule_idents[last_field_index].clone(),
93 )
94 .unwrap_err();
95 return Error::new(last_field.span(), e).to_compile_error();
96 }
97
98 if unsized_fields[0].field.index != fields.len() - unsized_fields.len()
99 && unsized_fields[0].field.field.ident.is_none()
100 {
101 return Error::new(
102 unsized_fields.first().unwrap().field.field.span(),
103 "#[make_varule] requires its unsized fields to be at the end for tuple structs",
104 )
105 .to_compile_error();
106 }
107
108 let unsized_field_info = UnsizedFields::new(unsized_fields, attrs.vzv_format);
109
110 let mut field_inits = crate::ule::make_ule_fields(&sized_fields);
111 let last_field_ule = unsized_field_info.varule_ty();
112
113 let setter = unsized_field_info.varule_setter();
114 let vis = &unsized_field_info.varule_vis();
115 field_inits.push(quote!(#vis #setter #last_field_ule));
116
117 let semi = utils::semi_for(fields);
118 let repr_attr = utils::repr_for(fields);
119 let field_inits = utils::wrap_field_inits(&field_inits, fields);
120 let vis = &input.vis;
121
122 let doc = format!(
123 "[`VarULE`](zerovec::ule::VarULE) type for [`{name}`]. See [`{name}`] for documentation."
124 );
125 let varule_struct: DeriveInput = parse_quote!(
126 #[repr(#repr_attr)]
127 #[doc = #doc]
128 #[allow(missing_docs)]
129 #vis struct #ule_name #field_inits #semi
130 );
131
132 let derived = crate::varule::derive_impl(&varule_struct, unsized_field_info.varule_validator());
133
134 let maybe_lt_bound = lt.as_ref().map(|lt| quote!(<#lt>));
135
136 let encode_impl = make_encode_impl(
137 &sized_fields,
138 &unsized_field_info,
139 name,
140 &ule_name,
141 &maybe_lt_bound,
142 );
143
144 let zf_and_from_impl = make_zf_and_from_impl(
145 &sized_fields,
146 &unsized_field_info,
147 fields,
148 name,
149 &ule_name,
150 lt,
151 input_span,
152 attrs.skip_from,
153 );
154
155 let eq_impl = quote!(
156 impl core::cmp::PartialEq for #ule_name {
157 fn eq(&self, other: &Self) -> bool {
158 <Self as zerovec::ule::VarULE>::as_bytes(&self)
161 == <Self as zerovec::ule::VarULE>::as_bytes(&other)
162 }
163 }
164
165 impl core::cmp::Eq for #ule_name {}
166 );
167
168 let zerofrom_fq_path =
169 quote!(<#name as zerovec::__zerovec_internal_reexport::ZeroFrom<#ule_name>>);
170
171 let maybe_ord_impls = if attrs.skip_ord {
172 quote!()
173 } else {
174 quote!(
175 impl core::cmp::PartialOrd for #ule_name {
176 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
177 Some(self.cmp(other))
178 }
179 }
180
181 impl core::cmp::Ord for #ule_name {
182 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
183 let this = #zerofrom_fq_path::zero_from(self);
184 let other = #zerofrom_fq_path::zero_from(other);
185 <#name as core::cmp::Ord>::cmp(&this, &other)
186 }
187 }
188 )
189 };
190
191 let maybe_debug = if attrs.debug {
192 quote!(
193 impl core::fmt::Debug for #ule_name {
194 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
195 let this = #zerofrom_fq_path::zero_from(self);
196 <#name as core::fmt::Debug>::fmt(&this, f)
197 }
198 }
199 )
200 } else {
201 quote!()
202 };
203
204 let maybe_toowned = if !attrs.skip_toowned {
205 quote!(
206 impl zerovec::__zerovec_internal_reexport::borrow::ToOwned for #ule_name {
207 type Owned = zerovec::__zerovec_internal_reexport::boxed::Box<Self>;
208 fn to_owned(&self) -> Self::Owned {
209 zerovec::ule::encode_varule_to_box(self)
210 }
211 }
212 )
213 } else {
214 quote!()
215 };
216
217 let zmkv = if attrs.skip_kv {
218 quote!()
219 } else {
220 quote!(
221 impl<'a> zerovec::maps::ZeroMapKV<'a> for #ule_name {
222 type Container = zerovec::VarZeroVec<'a, #ule_name>;
223 type Slice = zerovec::VarZeroSlice<#ule_name>;
224 type GetType = #ule_name;
225 type OwnedType = zerovec::__zerovec_internal_reexport::boxed::Box<#ule_name>;
226 }
227 )
228 };
229
230 let serde_path = quote!(zerovec::__zerovec_internal_reexport::serde);
231
232 let maybe_ser = if attrs.serialize {
233 quote!(
234 impl #serde_path::Serialize for #ule_name {
235 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: #serde_path::Serializer {
236 if serializer.is_human_readable() {
237 let this = #zerofrom_fq_path::zero_from(self);
238 <#name as #serde_path::Serialize>::serialize(&this, serializer)
239 } else {
240 serializer.serialize_bytes(zerovec::ule::VarULE::as_bytes(self))
241 }
242 }
243 }
244 )
245 } else {
246 quote!()
247 };
248
249 let deserialize_error = format!("&{ule_name} can only deserialize in zero-copy ways");
250
251 let maybe_de = if attrs.deserialize {
252 quote!(
253 impl<'de> #serde_path::Deserialize<'de> for zerovec::__zerovec_internal_reexport::boxed::Box<#ule_name> {
254 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: #serde_path::Deserializer<'de> {
255 if deserializer.is_human_readable() {
256 let this = <#name as #serde_path::Deserialize>::deserialize(deserializer)?;
257 Ok(zerovec::ule::encode_varule_to_box(&this))
258 } else {
259 let deserialized = <& #ule_name>::deserialize(deserializer)?;
261 Ok(zerovec::ule::VarULE::to_boxed(deserialized))
262 }
263 }
264 }
265 impl<'a, 'de: 'a> #serde_path::Deserialize<'de> for &'a #ule_name {
266 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: #serde_path::Deserializer<'de> {
267 if !deserializer.is_human_readable() {
268 let bytes = <&[u8]>::deserialize(deserializer)?;
269 <#ule_name as zerovec::ule::VarULE>::parse_bytes(bytes).map_err(#serde_path::de::Error::custom)
270 } else {
271 Err(#serde_path::de::Error::custom(#deserialize_error))
272 }
273 }
274 }
275 )
276 } else {
277 quote!()
278 };
279
280 let maybe_hash = if attrs.hash {
281 quote!(
282 #[allow(clippy::derive_hash_xor_eq)]
283 impl core::hash::Hash for #ule_name {
284 fn hash<H>(&self, state: &mut H) where H: core::hash::Hasher {
285 state.write(<#ule_name as zerovec::ule::VarULE>::as_bytes(&self));
286 }
287 }
288 )
289 } else {
290 quote!()
291 };
292
293 let maybe_multi_getters = if let Some(getters) = unsized_field_info.maybe_multi_getters() {
294 quote! {
295 impl #ule_name {
296 #getters
297 }
298 }
299 } else {
300 quote!()
301 };
302
303 quote!(
304 #input
305
306 #varule_struct
307
308 #maybe_multi_getters
309
310 #encode_impl
311
312 #zf_and_from_impl
313
314 #derived
315
316 #maybe_ord_impls
317
318 #eq_impl
319
320 #zmkv
321
322 #maybe_ser
323
324 #maybe_de
325
326 #maybe_debug
327
328 #maybe_toowned
329
330 #maybe_hash
331 )
332}
333
334#[allow(clippy::too_many_arguments)] fn make_zf_and_from_impl(
336 sized_fields: &[FieldInfo],
337 unsized_field_info: &UnsizedFields,
338 fields: &Fields,
339 name: &Ident,
340 ule_name: &Ident,
341 maybe_lt: Option<&Lifetime>,
342 span: Span,
343 skip_from: bool,
344) -> TokenStream2 {
345 if !unsized_field_info.has_zf() {
346 return quote!();
347 }
348
349 let lt = if let Some(ref lt) = maybe_lt {
350 lt
351 } else {
352 return Error::new(
353 span,
354 "Can only generate ZeroFrom impls for types with lifetimes",
355 )
356 .to_compile_error();
357 };
358
359 let mut field_inits = sized_fields
360 .iter()
361 .map(|f| {
362 let ty = &f.field.ty;
363 let accessor = &f.accessor;
364 let setter = f.setter();
365 quote!(#setter <#ty as zerovec::ule::AsULE>::from_unaligned(other.#accessor))
366 })
367 .collect::<Vec<_>>();
368
369 unsized_field_info.push_zf_setters(lt, &mut field_inits);
370
371 let field_inits = utils::wrap_field_inits(&field_inits, fields);
372 let zerofrom_trait = quote!(zerovec::__zerovec_internal_reexport::ZeroFrom);
373
374 let maybe_from = if skip_from {
375 quote!()
376 } else {
377 quote!(
378 impl<#lt> From<&#lt #ule_name> for #name<#lt> {
379 fn from(other: &#lt #ule_name) -> Self {
380 <Self as #zerofrom_trait<#lt, #ule_name>>::zero_from(other)
381 }
382 }
383 )
384 };
385 quote!(
386 impl <#lt> #zerofrom_trait <#lt, #ule_name> for #name <#lt> {
387 fn zero_from(other: &#lt #ule_name) -> Self {
388 Self #field_inits
389 }
390 }
391
392 #maybe_from
393 )
394}
395
396fn make_encode_impl(
397 sized_fields: &[FieldInfo],
398 unsized_field_info: &UnsizedFields,
399 name: &Ident,
400 ule_name: &Ident,
401 maybe_lt_bound: &Option<TokenStream2>,
402) -> TokenStream2 {
403 let mut lengths = vec![];
404
405 for field in sized_fields {
406 let ty = &field.field.ty;
407 lengths.push(quote!(::core::mem::size_of::<<#ty as zerovec::ule::AsULE>::ULE>()));
408 }
409
410 let (encoders, remaining_offset) = utils::generate_per_field_offsets(
411 sized_fields,
412 true,
413 |field, prev_offset_ident, size_ident| {
414 let ty = &field.field.ty;
415 let accessor = &field.accessor;
416 quote!(
417 #[allow(clippy::indexing_slicing)]
420 let out = &mut dst[#prev_offset_ident .. #prev_offset_ident + #size_ident];
421 let unaligned = zerovec::ule::AsULE::to_unaligned(self.#accessor);
422 let unaligned_slice = &[unaligned];
423 let src = <<#ty as zerovec::ule::AsULE>::ULE as zerovec::ule::ULE>::slice_as_bytes(unaligned_slice);
424 out.copy_from_slice(src);
425 )
426 },
427 );
428
429 let last_encode_len = unsized_field_info.encode_len();
430 let last_encode_write = unsized_field_info.encode_write(quote!(out));
431 quote!(
432 unsafe impl #maybe_lt_bound zerovec::ule::EncodeAsVarULE<#ule_name> for #name #maybe_lt_bound {
433 fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R {
435 unreachable!("other two methods implemented")
436 }
437
438 fn encode_var_ule_len(&self) -> usize {
440 #(#lengths +)* #last_encode_len
441 }
442
443 fn encode_var_ule_write(&self, mut dst: &mut [u8]) {
445 debug_assert_eq!(self.encode_var_ule_len(), dst.len());
446 #encoders
447
448
449 #[allow(clippy::indexing_slicing)]
452 let out = &mut dst[#remaining_offset..];
453 #last_encode_write
454 }
455 }
456
457 unsafe impl #maybe_lt_bound zerovec::ule::EncodeAsVarULE<#ule_name> for &'_ #name #maybe_lt_bound {
461 fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R {
463 unreachable!("other two methods implemented")
464 }
465
466 fn encode_var_ule_len(&self) -> usize {
468 (**self).encode_var_ule_len()
469 }
470
471 fn encode_var_ule_write(&self, mut dst: &mut [u8]) {
473 (**self).encode_var_ule_write(dst)
474 }
475 }
476 )
477}
478
479#[derive(Copy, Clone, Debug)]
483enum OwnULETy<'a> {
484 Slice(&'a Type),
486 Str,
488}
489
490#[derive(Clone, Debug)]
492enum UnsizedFieldKind<'a> {
493 Cow(OwnULETy<'a>),
494 VarZeroCow(OwnULETy<'a>),
495 ZeroVec(&'a Type),
496 VarZeroVec(&'a Type),
497 Custom(&'a TypePath, Ident),
499
500 Growable(OwnULETy<'a>),
502 Boxed(OwnULETy<'a>),
503 Ref(OwnULETy<'a>),
504}
505
506#[derive(Clone, Debug)]
507struct UnsizedField<'a> {
508 kind: UnsizedFieldKind<'a>,
509 field: FieldInfo<'a>,
510}
511
512struct UnsizedFields<'a> {
513 fields: Vec<UnsizedField<'a>>,
514 format_param: TokenStream2,
515}
516
517impl<'a> UnsizedFields<'a> {
518 fn new(fields: Vec<UnsizedField<'a>>, format_param: Option<TokenStream2>) -> Self {
520 assert!(!fields.is_empty(), "Must have at least one unsized field");
521
522 let format_param = format_param.unwrap_or_else(|| quote!(zerovec::vecs::Index16));
523 Self {
524 fields,
525 format_param,
526 }
527 }
528
529 fn varule_ty(&self) -> TokenStream2 {
531 let len = self.fields.len();
532 let format_param = &self.format_param;
533 if len == 1 {
534 self.fields[0].kind.varule_ty()
535 } else {
536 quote!(zerovec::ule::MultiFieldsULE::<#len, #format_param>)
537 }
538 }
539
540 fn varule_accessor(&self) -> TokenStream2 {
542 if self.fields.len() == 1 {
543 self.fields[0].field.accessor.clone()
544 } else if self.fields[0].field.field.ident.is_some() {
545 quote!(unsized_fields)
546 } else {
547 self.fields[0].field.accessor.clone()
549 }
550 }
551
552 fn varule_setter(&self) -> TokenStream2 {
554 if self.fields.len() == 1 {
555 self.fields[0].field.setter()
556 } else if self.fields[0].field.field.ident.is_some() {
557 quote!(unsized_fields: )
558 } else {
559 quote!()
560 }
561 }
562
563 fn varule_vis(&self) -> TokenStream2 {
564 if self.fields.len() == 1 {
565 self.fields[0].field.field.vis.to_token_stream()
566 } else {
567 quote!()
569 }
570 }
571
572 fn has_zf(&self) -> bool {
574 self.fields.iter().all(|f| f.kind.has_zf())
575 }
576
577 fn encode_write(&self, out: TokenStream2) -> TokenStream2 {
579 let len = self.fields.len();
580 let format_param = &self.format_param;
581 if len == 1 {
582 self.fields[0].encode_func(quote!(encode_var_ule_write), quote!(#out))
583 } else {
584 let mut lengths = vec![];
585 let mut writers = vec![];
586 for (i, field) in self.fields.iter().enumerate() {
587 lengths.push(field.encode_func(quote!(encode_var_ule_len), quote!()));
588 let (encodeable_ty, encodeable) = field.encodeable_tokens();
589 let varule_ty = field.kind.varule_ty();
590 writers
591 .push(quote!(multi.set_field_at::<#varule_ty, #encodeable_ty>(#i, #encodeable)))
592 }
593
594 quote!(
595 let lengths = [#(#lengths),*];
596 let mut multi = zerovec::ule::MultiFieldsULE::<#len, #format_param>::new_from_lengths_partially_initialized(lengths, #out);
598 unsafe {
599 #(#writers;)*
600 }
601 )
602 }
603 }
604
605 fn encode_len(&self) -> TokenStream2 {
607 let len = self.fields.len();
608 let format_param = &self.format_param;
609 if len == 1 {
610 self.fields[0].encode_func(quote!(encode_var_ule_len), quote!())
611 } else {
612 let mut lengths = vec![];
613 for field in self.fields.iter() {
614 lengths.push(field.encode_func(quote!(encode_var_ule_len), quote!()));
615 }
616 quote!(zerovec::ule::MultiFieldsULE::<#len, #format_param>::compute_encoded_len_for([#(#lengths),*]))
618 }
619 }
620
621 fn push_zf_setters(&self, lt: &Lifetime, field_inits: &mut Vec<TokenStream2>) {
623 let zerofrom_trait = quote!(zerovec::__zerovec_internal_reexport::ZeroFrom);
624 if self.fields.len() == 1 {
625 let accessor = self.fields[0].field.accessor.clone();
626 let setter = self.fields[0].field.setter();
627 let last_field_ty = &self.fields[0].field.field.ty;
628 let last_field_ule_ty = self.fields[0].kind.varule_ty();
629 field_inits.push(quote!(#setter <#last_field_ty as #zerofrom_trait <#lt, #last_field_ule_ty>>::zero_from(&other.#accessor) ));
630 } else {
631 for field in self.fields.iter() {
632 let setter = field.field.setter();
633 let getter = field.field.getter();
634 let field_ty = &field.field.field.ty;
635 let field_ule_ty = field.kind.varule_ty();
636
637 field_inits.push(quote!(#setter
638 <#field_ty as #zerofrom_trait <#lt, #field_ule_ty>>::zero_from(&other.#getter())
639 ));
640 }
641 }
642 }
643
644 fn maybe_multi_getters(&self) -> Option<TokenStream2> {
645 if self.fields.len() == 1 {
646 None
647 } else {
648 let multi_accessor = self.varule_accessor();
649 let field_getters = self.fields.iter().enumerate().map(|(i, field)| {
650 let getter = field.field.getter();
651
652 let field_ule_ty = field.kind.varule_ty();
653 let doc_name = field.field.getter_doc_name();
654 let doc = format!("Access the VarULE type behind {doc_name}");
655 quote!(
656 #[doc = #doc]
657 pub fn #getter<'a>(&'a self) -> &'a #field_ule_ty {
658 unsafe {
659 self.#multi_accessor.get_field::<#field_ule_ty>(#i)
660 }
661 }
662 )
663 });
664
665 Some(quote!(#(#field_getters)*))
666 }
667 }
668
669 fn varule_validator(&self) -> Option<TokenStream2> {
673 let len = self.fields.len();
674 let format_param = &self.format_param;
675 if len == 1 {
676 None
677 } else {
678 let mut validators = vec![];
679 for (i, field) in self.fields.iter().enumerate() {
680 let varule_ty = field.kind.varule_ty();
681 validators.push(quote!(multi.validate_field::<#varule_ty>(#i)?;));
682 }
683
684 Some(quote!(
685 let multi = zerovec::ule::MultiFieldsULE::<#len, #format_param>::parse_bytes(last_field_bytes)?;
686 unsafe {
687 #(#validators)*
688 }
689 ))
690 }
691 }
692}
693
694impl<'a> UnsizedField<'a> {
695 fn new(
696 field: &'a Field,
697 index: usize,
698 custom_varule_ident: Option<Ident>,
699 ) -> Result<Self, String> {
700 Ok(UnsizedField {
701 kind: UnsizedFieldKind::new(&field.ty, custom_varule_ident)?,
702 field: FieldInfo::new_for_field(field, index),
703 })
704 }
705
706 fn encode_func(&self, method: TokenStream2, additional_args: TokenStream2) -> TokenStream2 {
709 let encodeas_trait = quote!(zerovec::ule::EncodeAsVarULE);
710 let (encodeable_ty, encodeable) = self.encodeable_tokens();
711 let varule_ty = self.kind.varule_ty();
712 quote!(<#encodeable_ty as #encodeas_trait<#varule_ty>>::#method(#encodeable, #additional_args))
713 }
714
715 fn encodeable_tokens(&self) -> (TokenStream2, TokenStream2) {
717 let accessor = self.field.accessor.clone();
718 let value = quote!(self.#accessor);
719 let encodeable = self.kind.encodeable_value(value);
720 let encodeable_ty = self.kind.encodeable_ty();
721 (encodeable_ty, encodeable)
722 }
723}
724
725impl<'a> UnsizedFieldKind<'a> {
726 fn new(
728 ty: &'a Type,
729 custom_varule_ident: Option<Ident>,
730 ) -> Result<UnsizedFieldKind<'a>, String> {
731 static PATH_TYPE_IDENTITY_ERROR: &str =
732 "Can only automatically detect corresponding VarULE types for path types \
733 that are Cow, ZeroVec, VarZeroVec, Box, String, or Vec";
734 static PATH_TYPE_GENERICS_ERROR: &str =
735 "Can only automatically detect corresponding VarULE types for path \
736 types with at most one lifetime and at most one generic parameter. VarZeroVecFormat
737 types are not currently supported";
738 match *ty {
739 Type::Reference(ref tyref) => OwnULETy::new(&tyref.elem, "reference").map(UnsizedFieldKind::Ref),
740 Type::Path(ref typath) => {
741 if let Some(custom_varule_ident) = custom_varule_ident {
742 return Ok(UnsizedFieldKind::Custom(typath, custom_varule_ident));
743 }
744 if typath.path.segments.len() != 1 {
745 return Err("Can only automatically detect corresponding VarULE types for \
746 path types with a single path segment".into());
747 }
748 let segment = typath.path.segments.first().unwrap();
749 match segment.arguments {
750 PathArguments::None => {
751 if segment.ident == "String" {
752 Ok(UnsizedFieldKind::Growable(OwnULETy::Str))
753 } else {
754 Err(PATH_TYPE_IDENTITY_ERROR.into())
755 }
756 }
757 PathArguments::AngleBracketed(ref params) => {
758 let mut lifetime = None;
760 let mut generic = None;
761 for param in ¶ms.args {
762 match param {
763 GenericArgument::Lifetime(ref lt) if lifetime.is_none() => {
764 lifetime = Some(lt)
765 }
766 GenericArgument::Type(ref ty) if generic.is_none() => {
767 generic = Some(ty)
768 }
769 _ => return Err(PATH_TYPE_GENERICS_ERROR.into()),
770 }
771 }
772
773 let generic = if let Some(g) = generic {
776 g
777 } else {
778 return Err(PATH_TYPE_GENERICS_ERROR.into());
779 };
780
781 let ident = segment.ident.to_string();
782
783 if lifetime.is_some() {
784 match &*ident {
785 "ZeroVec" => Ok(UnsizedFieldKind::ZeroVec(generic)),
786 "VarZeroVec" => Ok(UnsizedFieldKind::VarZeroVec(generic)),
787 "Cow" => OwnULETy::new(generic, "Cow").map(UnsizedFieldKind::Cow),
788 "VarZeroCow" => OwnULETy::new(generic, "VarZeroCow").map(UnsizedFieldKind::VarZeroCow),
789 _ => Err(PATH_TYPE_IDENTITY_ERROR.into()),
790 }
791 } else {
792 match &*ident {
793 "Vec" => Ok(UnsizedFieldKind::Growable(OwnULETy::Slice(generic))),
794 "Box" => OwnULETy::new(generic, "Box").map(UnsizedFieldKind::Boxed),
795 _ => Err(PATH_TYPE_IDENTITY_ERROR.into()),
796 }
797 }
798 }
799 _ => Err("Can only automatically detect corresponding VarULE types for path types \
800 with none or angle bracketed generics".into()),
801 }
802 }
803 _ => Err("Can only automatically detect corresponding VarULE types for path and reference types".into()),
804 }
805 }
806 fn varule_ty(&self) -> TokenStream2 {
808 match *self {
809 Self::Ref(ref inner)
810 | Self::Cow(ref inner)
811 | Self::VarZeroCow(ref inner)
812 | Self::Boxed(ref inner)
813 | Self::Growable(ref inner) => {
814 let inner_ule = inner.varule_ty();
815 quote!(#inner_ule)
816 }
817 Self::Custom(_, ref name) => quote!(#name),
818 Self::ZeroVec(ref inner) => quote!(zerovec::ZeroSlice<#inner>),
819 Self::VarZeroVec(ref inner) => quote!(zerovec::VarZeroSlice<#inner>),
820 }
821 }
822
823 fn encodeable_value(&self, value: TokenStream2) -> TokenStream2 {
825 match *self {
826 Self::Ref(_)
827 | Self::Cow(_)
828 | Self::VarZeroCow(_)
829 | Self::Growable(_)
830 | Self::Boxed(_) => quote!(&*#value),
831
832 Self::Custom(..) => quote!(&#value),
833 Self::ZeroVec(_) | Self::VarZeroVec(_) => quote!(&*#value),
834 }
835 }
836
837 fn encodeable_ty(&self) -> TokenStream2 {
839 match *self {
840 Self::Ref(ref inner)
841 | Self::Cow(ref inner)
842 | Self::VarZeroCow(ref inner)
843 | Self::Growable(ref inner)
844 | Self::Boxed(ref inner) => inner.varule_ty(),
845
846 Self::Custom(ref path, _) => quote!(#path),
847 Self::ZeroVec(ref ty) => quote!(zerovec::ZeroSlice<#ty>),
848 Self::VarZeroVec(ref ty) => quote!(zerovec::VarZeroSlice<#ty>),
849 }
850 }
851
852 fn has_zf(&self) -> bool {
853 matches!(
854 *self,
855 Self::Ref(_)
856 | Self::Cow(_)
857 | Self::VarZeroCow(_)
858 | Self::ZeroVec(_)
859 | Self::VarZeroVec(_)
860 | Self::Custom(..)
861 )
862 }
863}
864
865impl<'a> OwnULETy<'a> {
866 fn new(ty: &'a Type, context: &str) -> Result<Self, String> {
867 match *ty {
868 Type::Slice(ref slice) => Ok(OwnULETy::Slice(&slice.elem)),
869 Type::Path(ref typath) => {
870 if typath.path.is_ident("str") {
871 Ok(OwnULETy::Str)
872 } else {
873 Err(format!("Cannot automatically detect corresponding VarULE type for non-str path type inside a {context}"))
874 }
875 }
876 _ => Err(format!("Cannot automatically detect corresponding VarULE type for non-slice/path type inside a {context}")),
877 }
878 }
879
880 fn varule_ty(&self) -> TokenStream2 {
882 match *self {
883 OwnULETy::Slice(s) => quote!([#s]),
884 OwnULETy::Str => quote!(str),
885 }
886 }
887}