1use proc_macro2::Span;
12use quote::quote;
13use syn::*;
14
15use crate::error_message::ParentRef;
16use crate::scope::{AsItemsScope, FromEventsScope};
17use crate::types::{
18 as_xml_text_fn, from_xml_text_fn, string_ty, text_codec_decode_fn, text_codec_encode_fn,
19};
20
21use super::{Field, FieldBuilderPart, FieldIteratorPart, FieldTempInit};
22
23pub(super) struct TextField {
25 pub(super) codec: Option<Expr>,
27}
28
29impl Field for TextField {
30 fn make_builder_part(
31 &self,
32 scope: &FromEventsScope,
33 _container_name: &ParentRef,
34 member: &Member,
35 ty: &Type,
36 ) -> Result<FieldBuilderPart> {
37 let FromEventsScope { ref text, .. } = scope;
38 let field_access = scope.access_field(member);
39 let finalize = match self.codec {
40 Some(ref codec) => {
41 let decode = text_codec_decode_fn(ty.clone());
42 quote! {
43 #decode(&#codec, #field_access)?
44 }
45 }
46 None => {
47 let from_xml_text = from_xml_text_fn(ty.clone());
48 quote! { #from_xml_text(#field_access)? }
49 }
50 };
51
52 Ok(FieldBuilderPart::Text {
53 value: FieldTempInit {
54 init: quote! { ::xso::exports::alloc::string::String::new() },
55 ty: string_ty(Span::call_site()),
56 },
57 collect: quote! {
58 #field_access.push_str(#text.as_str());
59 },
60 finalize,
61 })
62 }
63
64 fn make_iterator_part(
65 &self,
66 _scope: &AsItemsScope,
67 _container_name: &ParentRef,
68 bound_name: &Ident,
69 _member: &Member,
70 ty: &Type,
71 ) -> Result<FieldIteratorPart> {
72 let generator = match self.codec {
73 Some(ref codec) => {
74 let encode = text_codec_encode_fn(ty.clone());
75 quote! { #encode(&#codec, #bound_name)? }
76 }
77 None => {
78 let as_xml_text = as_xml_text_fn(ty.clone());
79 quote! { ::core::option::Option::Some(#as_xml_text(#bound_name)?) }
80 }
81 };
82
83 Ok(FieldIteratorPart::Text { generator })
84 }
85
86 fn captures_text(&self) -> bool {
87 true
88 }
89}