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);
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_impl = make_zf_impl(
145 &sized_fields,
146 &unsized_field_info,
147 fields,
148 name,
149 &ule_name,
150 lt,
151 input_span,
152 );
153
154 let eq_impl = quote!(
155 impl core::cmp::PartialEq for #ule_name {
156 fn eq(&self, other: &Self) -> bool {
157 <Self as zerovec::ule::VarULE>::as_byte_slice(&self)
160 == <Self as zerovec::ule::VarULE>::as_byte_slice(&other)
161 }
162 }
163
164 impl core::cmp::Eq for #ule_name {}
165 );
166
167 let zerofrom_fq_path =
168 quote!(<#name as zerovec::__zerovec_internal_reexport::ZeroFrom<#ule_name>>);
169
170 let maybe_ord_impls = if attrs.skip_ord {
171 quote!()
172 } else {
173 quote!(
174 impl core::cmp::PartialOrd for #ule_name {
175 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
176 Some(self.cmp(other))
177 }
178 }
179
180 impl core::cmp::Ord for #ule_name {
181 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
182 let this = #zerofrom_fq_path::zero_from(self);
183 let other = #zerofrom_fq_path::zero_from(other);
184 <#name as core::cmp::Ord>::cmp(&this, &other)
185 }
186 }
187 )
188 };
189
190 let maybe_debug = if attrs.debug {
191 quote!(
192 impl core::fmt::Debug for #ule_name {
193 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
194 let this = #zerofrom_fq_path::zero_from(self);
195 <#name as core::fmt::Debug>::fmt(&this, f)
196 }
197 }
198 )
199 } else {
200 quote!()
201 };
202
203 let zmkv = if attrs.skip_kv {
204 quote!()
205 } else {
206 quote!(
207 impl<'a> zerovec::maps::ZeroMapKV<'a> for #ule_name {
208 type Container = zerovec::VarZeroVec<'a, #ule_name>;
209 type Slice = zerovec::VarZeroSlice<#ule_name>;
210 type GetType = #ule_name;
211 type OwnedType = zerovec::__zerovec_internal_reexport::boxed::Box<#ule_name>;
212 }
213 )
214 };
215
216 let serde_path = quote!(zerovec::__zerovec_internal_reexport::serde);
217
218 let maybe_ser = if attrs.serialize {
219 quote!(
220 impl #serde_path::Serialize for #ule_name {
221 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: #serde_path::Serializer {
222 let this = #zerofrom_fq_path::zero_from(self);
223 <#name as #serde_path::Serialize>::serialize(&this, serializer)
224 }
225 }
226 )
227 } else {
228 quote!()
229 };
230
231 let maybe_de = if attrs.deserialize {
232 quote!(
233 impl<'de> #serde_path::Deserialize<'de> for zerovec::__zerovec_internal_reexport::boxed::Box<#ule_name> {
234 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: #serde_path::Deserializer<'de> {
235 let this = <#name as #serde_path::Deserialize>::deserialize(deserializer)?;
236 Ok(zerovec::ule::encode_varule_to_box(&this))
237 }
238 }
239 )
240 } else {
241 quote!()
242 };
243
244 let maybe_hash = if attrs.hash {
245 quote!(
246 #[allow(clippy::derive_hash_xor_eq)]
247 impl core::hash::Hash for #ule_name {
248 fn hash<H>(&self, state: &mut H) where H: core::hash::Hasher {
249 state.write(<#ule_name as zerovec::ule::VarULE>::as_byte_slice(&self));
250 }
251 }
252 )
253 } else {
254 quote!()
255 };
256
257 let maybe_multi_getters = if let Some(getters) = unsized_field_info.maybe_multi_getters() {
258 quote! {
259 impl #ule_name {
260 #getters
261 }
262 }
263 } else {
264 quote!()
265 };
266
267 quote!(
268 #input
269
270 #varule_struct
271
272 #maybe_multi_getters
273
274 #encode_impl
275
276 #zf_impl
277
278 #derived
279
280 #maybe_ord_impls
281
282 #eq_impl
283
284 #zmkv
285
286 #maybe_ser
287
288 #maybe_de
289
290 #maybe_debug
291
292 #maybe_hash
293 )
294}
295
296fn make_zf_impl(
297 sized_fields: &[FieldInfo],
298 unsized_field_info: &UnsizedFields,
299 fields: &Fields,
300 name: &Ident,
301 ule_name: &Ident,
302 maybe_lt: Option<&Lifetime>,
303 span: Span,
304) -> TokenStream2 {
305 if !unsized_field_info.has_zf() {
306 return quote!();
307 }
308
309 let lt = if let Some(ref lt) = maybe_lt {
310 lt
311 } else {
312 return Error::new(
313 span,
314 "Can only generate ZeroFrom impls for types with lifetimes",
315 )
316 .to_compile_error();
317 };
318
319 let mut field_inits = sized_fields
320 .iter()
321 .map(|f| {
322 let ty = &f.field.ty;
323 let accessor = &f.accessor;
324 let setter = f.setter();
325 quote!(#setter <#ty as zerovec::ule::AsULE>::from_unaligned(other.#accessor))
326 })
327 .collect::<Vec<_>>();
328
329 unsized_field_info.push_zf_setters(lt, &mut field_inits);
330
331 let field_inits = utils::wrap_field_inits(&field_inits, fields);
332 let zerofrom_trait = quote!(zerovec::__zerovec_internal_reexport::ZeroFrom);
333 quote!(
334 impl <#lt> #zerofrom_trait <#lt, #ule_name> for #name <#lt> {
335 fn zero_from(other: &#lt #ule_name) -> Self {
336 Self #field_inits
337 }
338 }
339 )
340}
341
342fn make_encode_impl(
343 sized_fields: &[FieldInfo],
344 unsized_field_info: &UnsizedFields,
345 name: &Ident,
346 ule_name: &Ident,
347 maybe_lt_bound: &Option<TokenStream2>,
348) -> TokenStream2 {
349 let mut lengths = vec![];
350
351 for field in sized_fields {
352 let ty = &field.field.ty;
353 lengths.push(quote!(::core::mem::size_of::<<#ty as zerovec::ule::AsULE>::ULE>()));
354 }
355
356 let (encoders, remaining_offset) = utils::generate_per_field_offsets(
357 sized_fields,
358 true,
359 |field, prev_offset_ident, size_ident| {
360 let ty = &field.field.ty;
361 let accessor = &field.accessor;
362 quote!(
363 #[allow(clippy::indexing_slicing)] let out = &mut dst[#prev_offset_ident .. #prev_offset_ident + #size_ident];
365 let unaligned = zerovec::ule::AsULE::to_unaligned(self.#accessor);
366 let unaligned_slice = &[unaligned];
367 let src = <<#ty as zerovec::ule::AsULE>::ULE as zerovec::ule::ULE>::as_byte_slice(unaligned_slice);
368 out.copy_from_slice(src);
369 )
370 },
371 );
372
373 let last_encode_len = unsized_field_info.encode_len();
374 let last_encode_write = unsized_field_info.encode_write(quote!(out));
375 quote!(
376 unsafe impl #maybe_lt_bound zerovec::ule::EncodeAsVarULE<#ule_name> for #name #maybe_lt_bound {
377 fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R {
379 unreachable!("other two methods implemented")
380 }
381
382 fn encode_var_ule_len(&self) -> usize {
384 #(#lengths +)* #last_encode_len
385 }
386
387 fn encode_var_ule_write(&self, mut dst: &mut [u8]) {
389 debug_assert_eq!(self.encode_var_ule_len(), dst.len());
390 #encoders
391
392 #[allow(clippy::indexing_slicing)] let out = &mut dst[#remaining_offset..];
394 #last_encode_write
395 }
396 }
397
398 unsafe impl #maybe_lt_bound zerovec::ule::EncodeAsVarULE<#ule_name> for &'_ #name #maybe_lt_bound {
402 fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R {
404 unreachable!("other two methods implemented")
405 }
406
407 fn encode_var_ule_len(&self) -> usize {
409 (**self).encode_var_ule_len()
410 }
411
412 fn encode_var_ule_write(&self, mut dst: &mut [u8]) {
414 (**self).encode_var_ule_write(dst)
415 }
416 }
417 )
418}
419
420#[derive(Copy, Clone, Debug)]
424enum OwnULETy<'a> {
425 Slice(&'a Type),
427 Str,
429}
430
431#[derive(Clone, Debug)]
433enum UnsizedFieldKind<'a> {
434 Cow(OwnULETy<'a>),
435 ZeroVec(&'a Type),
436 VarZeroVec(&'a Type),
437 Custom(&'a TypePath, Ident),
439
440 Growable(OwnULETy<'a>),
442 Boxed(OwnULETy<'a>),
443 Ref(OwnULETy<'a>),
444}
445
446#[derive(Clone, Debug)]
447struct UnsizedField<'a> {
448 kind: UnsizedFieldKind<'a>,
449 field: FieldInfo<'a>,
450}
451
452struct UnsizedFields<'a> {
453 fields: Vec<UnsizedField<'a>>,
454}
455
456impl<'a> UnsizedFields<'a> {
457 fn new(fields: Vec<UnsizedField<'a>>) -> Self {
458 assert!(!fields.is_empty(), "Must have at least one unsized field");
459 Self { fields }
460 }
461
462 fn varule_ty(&self) -> TokenStream2 {
464 if self.fields.len() == 1 {
465 self.fields[0].kind.varule_ty()
466 } else {
467 quote!(zerovec::ule::MultiFieldsULE)
468 }
469 }
470
471 fn varule_accessor(&self) -> TokenStream2 {
473 if self.fields.len() == 1 {
474 self.fields[0].field.accessor.clone()
475 } else if self.fields[0].field.field.ident.is_some() {
476 quote!(unsized_fields)
477 } else {
478 self.fields[0].field.accessor.clone()
480 }
481 }
482
483 fn varule_setter(&self) -> TokenStream2 {
485 if self.fields.len() == 1 {
486 self.fields[0].field.setter()
487 } else if self.fields[0].field.field.ident.is_some() {
488 quote!(unsized_fields: )
489 } else {
490 quote!()
491 }
492 }
493
494 fn varule_vis(&self) -> TokenStream2 {
495 if self.fields.len() == 1 {
496 self.fields[0].field.field.vis.to_token_stream()
497 } else {
498 quote!()
500 }
501 }
502
503 fn has_zf(&self) -> bool {
505 self.fields.iter().all(|f| f.kind.has_zf())
506 }
507
508 fn encode_write(&self, out: TokenStream2) -> TokenStream2 {
510 if self.fields.len() == 1 {
511 self.fields[0].encode_func(quote!(encode_var_ule_write), quote!(#out))
512 } else {
513 let mut lengths = vec![];
514 let mut writers = vec![];
515 for (i, field) in self.fields.iter().enumerate() {
516 lengths.push(field.encode_func(quote!(encode_var_ule_len), quote!()));
517 let (encodeable_ty, encodeable) = field.encodeable_tokens();
518 let varule_ty = field.kind.varule_ty();
519 writers
520 .push(quote!(multi.set_field_at::<#varule_ty, #encodeable_ty>(#i, #encodeable)))
521 }
522
523 quote!(
524 let lengths = [#(#lengths),*];
525 let mut multi = zerovec::ule::MultiFieldsULE::new_from_lengths_partially_initialized(&lengths, #out);
526 unsafe {
527 #(#writers;)*
528 }
529 )
530 }
531 }
532
533 fn encode_len(&self) -> TokenStream2 {
535 if self.fields.len() == 1 {
536 self.fields[0].encode_func(quote!(encode_var_ule_len), quote!())
537 } else {
538 let mut lengths = vec![];
539 for field in self.fields.iter() {
540 lengths.push(field.encode_func(quote!(encode_var_ule_len), quote!()));
541 }
542 quote!(zerovec::ule::MultiFieldsULE::compute_encoded_len_for(&[#(#lengths),*]))
543 }
544 }
545
546 fn push_zf_setters(&self, lt: &Lifetime, field_inits: &mut Vec<TokenStream2>) {
548 let zerofrom_trait = quote!(zerovec::__zerovec_internal_reexport::ZeroFrom);
549 if self.fields.len() == 1 {
550 let accessor = self.fields[0].field.accessor.clone();
551 let setter = self.fields[0].field.setter();
552 let last_field_ty = &self.fields[0].field.field.ty;
553 let last_field_ule_ty = self.fields[0].kind.varule_ty();
554 field_inits.push(quote!(#setter <#last_field_ty as #zerofrom_trait <#lt, #last_field_ule_ty>>::zero_from(&other.#accessor) ));
555 } else {
556 for field in self.fields.iter() {
557 let setter = field.field.setter();
558 let getter = field.field.getter();
559 let field_ty = &field.field.field.ty;
560 let field_ule_ty = field.kind.varule_ty();
561
562 field_inits.push(quote!(#setter
563 <#field_ty as #zerofrom_trait <#lt, #field_ule_ty>>::zero_from(&other.#getter())
564 ));
565 }
566 }
567 }
568
569 fn maybe_multi_getters(&self) -> Option<TokenStream2> {
570 if self.fields.len() == 1 {
571 None
572 } else {
573 let multi_accessor = self.varule_accessor();
574 let field_getters = self.fields.iter().enumerate().map(|(i, field)| {
575 let getter = field.field.getter();
576
577 let field_ule_ty = field.kind.varule_ty();
578 let doc_name = field.field.getter_doc_name();
579 let doc = format!("Access the VarULE type behind {doc_name}");
580 quote!(
581 #[doc = #doc]
582 pub fn #getter<'a>(&'a self) -> &'a #field_ule_ty {
583 unsafe {
584 self.#multi_accessor.get_field::<#field_ule_ty>(#i)
585 }
586 }
587 )
588 });
589
590 Some(quote!(#(#field_getters)*))
591 }
592 }
593
594 fn varule_validator(&self) -> Option<TokenStream2> {
598 if self.fields.len() == 1 {
599 None
600 } else {
601 let mut validators = vec![];
602 for (i, field) in self.fields.iter().enumerate() {
603 let varule_ty = field.kind.varule_ty();
604 validators.push(quote!(multi.validate_field::<#varule_ty>(#i)?;));
605 }
606
607 Some(quote!(
608 let multi = zerovec::ule::MultiFieldsULE::parse_byte_slice(last_field_bytes)?;
609 unsafe {
610 #(#validators)*
611 }
612 ))
613 }
614 }
615}
616
617impl<'a> UnsizedField<'a> {
618 fn new(
619 field: &'a Field,
620 index: usize,
621 custom_varule_ident: Option<Ident>,
622 ) -> Result<Self, String> {
623 Ok(UnsizedField {
624 kind: UnsizedFieldKind::new(&field.ty, custom_varule_ident)?,
625 field: FieldInfo::new_for_field(field, index),
626 })
627 }
628
629 fn encode_func(&self, method: TokenStream2, additional_args: TokenStream2) -> TokenStream2 {
632 let encodeas_trait = quote!(zerovec::ule::EncodeAsVarULE);
633 let (encodeable_ty, encodeable) = self.encodeable_tokens();
634 let varule_ty = self.kind.varule_ty();
635 quote!(<#encodeable_ty as #encodeas_trait<#varule_ty>>::#method(#encodeable, #additional_args))
636 }
637
638 fn encodeable_tokens(&self) -> (TokenStream2, TokenStream2) {
640 let accessor = self.field.accessor.clone();
641 let value = quote!(self.#accessor);
642 let encodeable = self.kind.encodeable_value(value);
643 let encodeable_ty = self.kind.encodeable_ty();
644 (encodeable_ty, encodeable)
645 }
646}
647
648impl<'a> UnsizedFieldKind<'a> {
649 fn new(
651 ty: &'a Type,
652 custom_varule_ident: Option<Ident>,
653 ) -> Result<UnsizedFieldKind<'a>, String> {
654 static PATH_TYPE_IDENTITY_ERROR: &str =
655 "Can only automatically detect corresponding VarULE types for path types \
656 that are Cow, ZeroVec, VarZeroVec, Box, String, or Vec";
657 static PATH_TYPE_GENERICS_ERROR: &str =
658 "Can only automatically detect corresponding VarULE types for path \
659 types with at most one lifetime and at most one generic parameter. VarZeroVecFormat
660 types are not currently supported";
661 match *ty {
662 Type::Reference(ref tyref) => OwnULETy::new(&tyref.elem, "reference").map(UnsizedFieldKind::Ref),
663 Type::Path(ref typath) => {
664 if let Some(custom_varule_ident) = custom_varule_ident {
665 return Ok(UnsizedFieldKind::Custom(typath, custom_varule_ident));
666 }
667 if typath.path.segments.len() != 1 {
668 return Err("Can only automatically detect corresponding VarULE types for \
669 path types with a single path segment".into());
670 }
671 let segment = typath.path.segments.first().unwrap();
672 match segment.arguments {
673 PathArguments::None => {
674 if segment.ident == "String" {
675 Ok(UnsizedFieldKind::Growable(OwnULETy::Str))
676 } else {
677 Err(PATH_TYPE_IDENTITY_ERROR.into())
678 }
679 }
680 PathArguments::AngleBracketed(ref params) => {
681 let mut lifetime = None;
683 let mut generic = None;
684 for param in ¶ms.args {
685 match param {
686 GenericArgument::Lifetime(ref lt) if lifetime.is_none() => {
687 lifetime = Some(lt)
688 }
689 GenericArgument::Type(ref ty) if generic.is_none() => {
690 generic = Some(ty)
691 }
692 _ => return Err(PATH_TYPE_GENERICS_ERROR.into()),
693 }
694 }
695
696 let generic = if let Some(g) = generic {
699 g
700 } else {
701 return Err(PATH_TYPE_GENERICS_ERROR.into());
702 };
703
704 let ident = segment.ident.to_string();
705
706 if lifetime.is_some() {
707 match &*ident {
708 "ZeroVec" => Ok(UnsizedFieldKind::ZeroVec(generic)),
709 "VarZeroVec" => Ok(UnsizedFieldKind::VarZeroVec(generic)),
710 "Cow" => OwnULETy::new(generic, "Cow").map(UnsizedFieldKind::Cow),
711 _ => Err(PATH_TYPE_IDENTITY_ERROR.into()),
712 }
713 } else {
714 match &*ident {
715 "Vec" => Ok(UnsizedFieldKind::Growable(OwnULETy::Slice(generic))),
716 "Box" => OwnULETy::new(generic, "Box").map(UnsizedFieldKind::Boxed),
717 _ => Err(PATH_TYPE_IDENTITY_ERROR.into()),
718 }
719 }
720 }
721 _ => Err("Can only automatically detect corresponding VarULE types for path types \
722 with none or angle bracketed generics".into()),
723 }
724 }
725 _ => Err("Can only automatically detect corresponding VarULE types for path and reference types".into()),
726 }
727 }
728 fn varule_ty(&self) -> TokenStream2 {
730 match *self {
731 Self::Ref(ref inner)
732 | Self::Cow(ref inner)
733 | Self::Boxed(ref inner)
734 | Self::Growable(ref inner) => {
735 let inner_ule = inner.varule_ty();
736 quote!(#inner_ule)
737 }
738 Self::Custom(_, ref name) => quote!(#name),
739 Self::ZeroVec(ref inner) => quote!(zerovec::ZeroSlice<#inner>),
740 Self::VarZeroVec(ref inner) => quote!(zerovec::VarZeroSlice<#inner>),
741 }
742 }
743
744 fn encodeable_value(&self, value: TokenStream2) -> TokenStream2 {
746 match *self {
747 Self::Ref(_) | Self::Cow(_) | Self::Growable(_) | Self::Boxed(_) => quote!(&*#value),
748
749 Self::Custom(..) => quote!(&#value),
750 Self::ZeroVec(_) | Self::VarZeroVec(_) => quote!(&*#value),
751 }
752 }
753
754 fn encodeable_ty(&self) -> TokenStream2 {
756 match *self {
757 Self::Ref(ref inner)
758 | Self::Cow(ref inner)
759 | Self::Growable(ref inner)
760 | Self::Boxed(ref inner) => inner.varule_ty(),
761
762 Self::Custom(ref path, _) => quote!(#path),
763 Self::ZeroVec(ref ty) => quote!(zerovec::ZeroSlice<#ty>),
764 Self::VarZeroVec(ref ty) => quote!(zerovec::VarZeroSlice<#ty>),
765 }
766 }
767
768 fn has_zf(&self) -> bool {
769 matches!(
770 *self,
771 Self::Ref(_) | Self::Cow(_) | Self::ZeroVec(_) | Self::VarZeroVec(_) | Self::Custom(..)
772 )
773 }
774}
775
776impl<'a> OwnULETy<'a> {
777 fn new(ty: &'a Type, context: &str) -> Result<Self, String> {
778 match *ty {
779 Type::Slice(ref slice) => Ok(OwnULETy::Slice(&slice.elem)),
780 Type::Path(ref typath) => {
781 if typath.path.is_ident("str") {
782 Ok(OwnULETy::Str)
783 } else {
784 Err(format!("Cannot automatically detect corresponding VarULE type for non-str path type inside a {context}"))
785 }
786 }
787 _ => Err(format!("Cannot automatically detect corresponding VarULE type for non-slice/path type inside a {context}")),
788 }
789 }
790
791 fn varule_ty(&self) -> TokenStream2 {
793 match *self {
794 OwnULETy::Slice(s) => quote!([#s]),
795 OwnULETy::Str => quote!(str),
796 }
797 }
798}