derive_builder_core_fork_arti/
builder.rs

1use std::borrow::Cow;
2
3use proc_macro2::TokenStream;
4use quote::{format_ident, ToTokens, TokenStreamExt};
5use syn::punctuated::Punctuated;
6use syn::{self, Path, TraitBound, TraitBoundModifier, TypeParamBound};
7
8use doc_comment_from;
9use BuildMethod;
10use BuilderField;
11use BuilderPattern;
12use DeprecationNotes;
13use Setter;
14
15/// Builder, implementing `quote::ToTokens`.
16///
17/// # Examples
18///
19/// Will expand to something like the following (depending on settings):
20///
21/// ```rust,ignore
22/// # extern crate proc_macro2;
23/// # #[macro_use]
24/// # extern crate quote;
25/// # extern crate syn;
26/// # #[macro_use]
27/// # extern crate derive_builder_core;
28/// # use quote::TokenStreamExt;
29/// # use derive_builder_core::{Builder, DeprecationNotes};
30/// # fn main() {
31/// #    let builder = default_builder!();
32/// #
33/// #    assert_eq!(
34/// #       quote!(#builder).to_string(),
35/// #       {
36/// #           let mut result = quote!();
37/// #           #[cfg(not(feature = "clippy"))]
38/// #           result.append_all(quote!(#[allow(clippy::all)]));
39/// #
40/// #           result.append_all(quote!(
41/// #[derive(Clone)]
42/// pub struct FooBuilder {
43///     foo: u32,
44/// }
45///
46/// #[doc="Error type for FooBuilder"]
47/// #[derive(Debug)]
48/// #[non_exhaustive]
49/// pub enum FooBuilderError {
50///     /// Uninitialized field
51///     UninitializedField(&'static str),
52///     /// Custom validation error
53///     ValidationError(::derive_builder::export::core::string::String),
54/// }
55///
56/// impl ::derive_builder::export::core::convert::From<... various ...> for FooBuilderError {}
57///
58/// #[cfg(not(no_std))]
59/// impl std::error::Error for FooBuilderError {}
60/// #           ));
61/// #           #[cfg(not(feature = "clippy"))]
62/// #           result.append_all(quote!(#[allow(clippy::all)]));
63/// #
64/// #           result.append_all(quote!(
65///
66/// #[allow(dead_code)]
67/// impl FooBuilder {
68///     fn bar () -> {
69///         unimplemented!()
70///     }
71/// }
72///
73/// impl ::derive_builder::export::core::default::Default for FooBuilder {
74///     fn default() -> Self {
75///         Self {
76///            foo: ::derive_builder::export::core::default::Default::default(),
77///         }
78///     }
79/// }
80///
81/// #           ));
82/// #           result
83/// #       }.to_string()
84/// #   );
85/// # }
86/// ```
87#[derive(Debug)]
88pub struct Builder<'a> {
89    /// Enables code generation for this builder struct.
90    pub enabled: bool,
91    /// Name of this builder struct.
92    pub ident: syn::Ident,
93    /// Pattern of this builder struct.
94    pub pattern: BuilderPattern,
95    /// Traits to automatically derive on the builder type.
96    pub derives: &'a [Path],
97    /// Attributes to include on the builder `struct` declaration.
98    pub struct_attrs: &'a [syn::Attribute],
99    /// Attributes to include on the builder's inherent `impl` block.
100    pub impl_attrs: &'a [syn::Attribute],
101    /// When true, generate `impl Default for #ident` which calls the `create_empty` inherent method.
102    ///
103    /// Note that the name of `create_empty` can be overridden; see the `create_empty` field for more.
104    pub impl_default: bool,
105    /// The identifier of the inherent method that creates a builder with all fields set to
106    /// `None` or `PhantomData`.
107    ///
108    /// This method will be invoked by `impl Default` for the builder, but it is also accessible
109    /// to `impl` blocks on the builder that expose custom constructors.
110    pub create_empty: syn::Ident,
111    /// Type parameters and lifetimes attached to this builder's struct
112    /// definition.
113    pub generics: Option<&'a syn::Generics>,
114    /// Visibility of the builder struct, e.g. `syn::Visibility::Public`.
115    pub visibility: Cow<'a, syn::Visibility>,
116    /// Fields of the builder struct, e.g. `foo: u32,`
117    ///
118    /// Expects each entry to be terminated by a comma.
119    pub fields: Vec<TokenStream>,
120    /// Builder field initializers, e.g. `foo: Default::default(),`
121    ///
122    /// Expects each entry to be terminated by a comma.
123    pub field_initializers: Vec<TokenStream>,
124    /// Functions of the builder struct, e.g. `fn bar() -> { unimplemented!() }`
125    pub functions: Vec<TokenStream>,
126    /// Whether or not a generated error type is required.
127    ///
128    /// This would be `false` in the case where an already-existing error is to be used.
129    pub generate_error: bool,
130    /// Whether this builder must derive `Clone`.
131    ///
132    /// This is true even for a builder using the `owned` pattern if there is a field whose setter
133    /// uses a different pattern.
134    pub must_derive_clone: bool,
135    /// Doc-comment of the builder struct.
136    pub doc_comment: Option<syn::Attribute>,
137    /// Emit deprecation notes to the user.
138    pub deprecation_notes: DeprecationNotes,
139    /// Whether or not a libstd is used.
140    pub std: bool,
141}
142
143impl<'a> ToTokens for Builder<'a> {
144    fn to_tokens(&self, tokens: &mut TokenStream) {
145        if self.enabled {
146            let builder_vis = &self.visibility;
147            let builder_ident = &self.ident;
148            let bounded_generics = self.compute_impl_bounds();
149            let (impl_generics, _, _) = bounded_generics.split_for_impl();
150            let (struct_generics, ty_generics, where_clause) = self
151                .generics
152                .map(syn::Generics::split_for_impl)
153                .map(|(i, t, w)| (Some(i), Some(t), Some(w)))
154                .unwrap_or((None, None, None));
155            let builder_fields = &self.fields;
156            let builder_field_initializers = &self.field_initializers;
157            let create_empty = &self.create_empty;
158            let functions = &self.functions;
159
160            // Create the comma-separated set of derived traits for the builder
161            let derive_attr = {
162                let clone_trait: Path = parse_quote!(Clone);
163
164                let mut traits: Punctuated<&Path, Token![,]> = Default::default();
165                if self.must_derive_clone {
166                    traits.push(&clone_trait);
167                }
168                traits.extend(self.derives);
169
170                if traits.is_empty() {
171                    quote!()
172                } else {
173                    quote!(#[derive(#traits)])
174                }
175            };
176
177            let struct_attrs = self.struct_attrs;
178            let impl_attrs = self.impl_attrs;
179
180            let builder_doc_comment = &self.doc_comment;
181            let deprecation_notes = &self.deprecation_notes.as_item();
182
183            #[cfg(not(feature = "clippy"))]
184            tokens.append_all(quote!(#[allow(clippy::all)]));
185
186            // struct_attrs MUST come after derive_attr, otherwise attributes for a derived
187            // trait will appear before its derivation. As of rustc 1.59.0 this is a compiler
188            // warning; see https://github.com/rust-lang/rust/issues/79202
189            tokens.append_all(quote!(
190                #derive_attr
191                #(#struct_attrs)*
192                #builder_doc_comment
193                #builder_vis struct #builder_ident #struct_generics #where_clause {
194                    #(#builder_fields)*
195                }
196            ));
197
198            #[cfg(not(feature = "clippy"))]
199            tokens.append_all(quote!(#[allow(clippy::all)]));
200
201            tokens.append_all(quote!(
202                #(#impl_attrs)*
203                #[allow(dead_code)]
204                impl #impl_generics #builder_ident #ty_generics #where_clause {
205                    #(#functions)*
206                    #deprecation_notes
207
208                    /// Create an empty builder, with all fields set to `None` or `PhantomData`.
209                    fn #create_empty() -> Self {
210                        Self {
211                            #(#builder_field_initializers)*
212                        }
213                    }
214                }
215            ));
216
217            if self.impl_default {
218                tokens.append_all(quote!(
219                    impl #impl_generics ::derive_builder::export::core::default::Default for #builder_ident #ty_generics #where_clause {
220                        fn default() -> Self {
221                            Self::#create_empty()
222                        }
223                    }
224                ));
225            }
226
227            if self.generate_error {
228                let builder_error_ident = format_ident!("{}Error", builder_ident);
229                let builder_error_doc = format!("Error type for {}", builder_ident);
230
231                tokens.append_all(quote!(
232                    #[doc=#builder_error_doc]
233                    #[derive(Debug)]
234                    #[non_exhaustive]
235                    #builder_vis enum #builder_error_ident {
236                        /// Uninitialized field
237                        UninitializedField(&'static str),
238                        /// Custom validation error
239                        ValidationError(::derive_builder::export::core::string::String),
240                    }
241
242                    impl ::derive_builder::export::core::convert::From<::derive_builder::UninitializedFieldError> for #builder_error_ident {
243                        fn from(s: ::derive_builder::UninitializedFieldError) -> Self {
244                            Self::UninitializedField(s.field_name())
245                        }
246                    }
247
248                    impl ::derive_builder::export::core::convert::From<::derive_builder::export::core::string::String> for #builder_error_ident {
249                        fn from(s: ::derive_builder::export::core::string::String) -> Self {
250                            Self::ValidationError(s)
251                        }
252                    }
253
254                    impl ::derive_builder::export::core::fmt::Display for #builder_error_ident {
255                        fn fmt(&self, f: &mut ::derive_builder::export::core::fmt::Formatter) -> ::derive_builder::export::core::fmt::Result {
256                            match self {
257                                Self::UninitializedField(ref field) => write!(f, "`{}` must be initialized", field),
258                                Self::ValidationError(ref error) => write!(f, "{}", error),
259                            }
260                        }
261                    }
262                ));
263
264                if self.std {
265                    tokens.append_all(quote!(
266                        impl std::error::Error for #builder_error_ident {}
267
268                        impl<E: std::error::Error> ::derive_builder::export::core::convert::From<::derive_builder::SubfieldBuildError<E>> for #builder_error_ident {
269                            fn from(e: ::derive_builder::SubfieldBuildError<E>) -> Self {
270                                Self::ValidationError(::derive_builder::export::core::string::ToString::to_string(&e))
271                            }
272                        }
273                    ));
274                }
275            }
276        }
277    }
278}
279
280impl<'a> Builder<'a> {
281    /// Set a doc-comment for this item.
282    pub fn doc_comment(&mut self, s: String) -> &mut Self {
283        self.doc_comment = Some(doc_comment_from(s));
284        self
285    }
286
287    /// Add a field to the builder
288    pub fn push_field(&mut self, f: BuilderField) -> &mut Self {
289        self.fields.push(quote!(#f));
290        self.field_initializers.push(f.default_initializer_tokens());
291        self
292    }
293
294    /// Add a setter function to the builder
295    pub fn push_setter_fn(&mut self, f: Setter) -> &mut Self {
296        self.functions.push(quote!(#f));
297        self
298    }
299
300    /// Add final build function to the builder
301    pub fn push_build_fn(&mut self, f: BuildMethod) -> &mut Self {
302        self.functions.push(quote!(#f));
303        self
304    }
305
306    /// Add `Clone` trait bound to generic types for non-owned builders.
307    /// This enables target types to declare generics without requiring a
308    /// `Clone` impl. This is the same as how the built-in derives for
309    /// `Clone`, `Default`, `PartialEq`, and other traits work.
310    fn compute_impl_bounds(&self) -> syn::Generics {
311        if let Some(type_gen) = self.generics {
312            let mut generics = type_gen.clone();
313
314            if !self.pattern.requires_clone() || type_gen.type_params().next().is_none() {
315                return generics;
316            }
317
318            let clone_bound = TypeParamBound::Trait(TraitBound {
319                paren_token: None,
320                modifier: TraitBoundModifier::None,
321                lifetimes: None,
322                path: syn::parse_quote!(::derive_builder::export::core::clone::Clone),
323            });
324
325            for typ in generics.type_params_mut() {
326                typ.bounds.push(clone_bound.clone());
327            }
328
329            generics
330        } else {
331            Default::default()
332        }
333    }
334}
335
336/// Helper macro for unit tests. This is _only_ public in order to be accessible
337/// from doc-tests too.
338#[doc(hidden)]
339#[macro_export]
340macro_rules! default_builder {
341    () => {
342        Builder {
343            enabled: true,
344            ident: syn::Ident::new("FooBuilder", ::proc_macro2::Span::call_site()),
345            pattern: Default::default(),
346            derives: &vec![],
347            struct_attrs: &vec![],
348            impl_attrs: &vec![],
349            impl_default: true,
350            create_empty: syn::Ident::new("create_empty", ::proc_macro2::Span::call_site()),
351            generics: None,
352            visibility: ::std::borrow::Cow::Owned(parse_quote!(pub)),
353            fields: vec![quote!(foo: u32,)],
354            field_initializers: vec![quote!(foo: ::derive_builder::export::core::default::Default::default(), )],
355            functions: vec![quote!(fn bar() -> { unimplemented!() })],
356            generate_error: true,
357            must_derive_clone: true,
358            doc_comment: None,
359            deprecation_notes: DeprecationNotes::default(),
360            std: true,
361        }
362    };
363}
364
365#[cfg(test)]
366mod tests {
367    #[allow(unused_imports)]
368    use super::*;
369    use proc_macro2::TokenStream;
370    use syn::Ident;
371
372    fn add_generated_error(result: &mut TokenStream) {
373        result.append_all(quote!(
374            #[doc="Error type for FooBuilder"]
375            #[derive(Debug)]
376            #[non_exhaustive]
377            pub enum FooBuilderError {
378                /// Uninitialized field
379                UninitializedField(&'static str),
380                /// Custom validation error
381                ValidationError(::derive_builder::export::core::string::String),
382            }
383
384            impl ::derive_builder::export::core::convert::From<::derive_builder::UninitializedFieldError> for FooBuilderError {
385                fn from(s: ::derive_builder::UninitializedFieldError) -> Self {
386                    Self::UninitializedField(s.field_name())
387                }
388            }
389
390            impl ::derive_builder::export::core::convert::From<::derive_builder::export::core::string::String> for FooBuilderError {
391                fn from(s: ::derive_builder::export::core::string::String) -> Self {
392                    Self::ValidationError(s)
393                }
394            }
395
396            impl ::derive_builder::export::core::fmt::Display for FooBuilderError {
397                fn fmt(&self, f: &mut ::derive_builder::export::core::fmt::Formatter) -> ::derive_builder::export::core::fmt::Result {
398                    match self {
399                        Self::UninitializedField(ref field) => write!(f, "`{}` must be initialized", field),
400                        Self::ValidationError(ref error) => write!(f, "{}", error),
401                    }
402                }
403            }
404
405            impl std::error::Error for FooBuilderError {}
406
407            impl<E: std::error::Error> ::derive_builder::export::core::convert::From<::derive_builder::SubfieldBuildError<E>> for FooBuilderError {
408                fn from(e: ::derive_builder::SubfieldBuildError<E>) -> Self {
409                    Self::ValidationError(::derive_builder::export::core::string::ToString::to_string(&e))
410                }
411            }
412        ));
413    }
414
415    #[test]
416    fn simple() {
417        let builder = default_builder!();
418
419        assert_eq!(
420            quote!(#builder).to_string(),
421            {
422                let mut result = quote!();
423
424                #[cfg(not(feature = "clippy"))]
425                result.append_all(quote!(#[allow(clippy::all)]));
426
427                result.append_all(quote!(
428                    #[derive(Clone)]
429                    pub struct FooBuilder {
430                        foo: u32,
431                    }
432                ));
433
434                #[cfg(not(feature = "clippy"))]
435                result.append_all(quote!(#[allow(clippy::all)]));
436
437                result.append_all(quote!(
438                    #[allow(dead_code)]
439                    impl FooBuilder {
440                        fn bar () -> {
441                            unimplemented!()
442                        }
443
444                        /// Create an empty builder, with all fields set to `None` or `PhantomData`.
445                        fn create_empty() -> Self {
446                            Self {
447                                foo: ::derive_builder::export::core::default::Default::default(),
448                            }
449                        }
450                    }
451
452                    impl ::derive_builder::export::core::default::Default for FooBuilder {
453                        fn default() -> Self {
454                            Self::create_empty()
455                        }
456                    }
457                ));
458
459                add_generated_error(&mut result);
460
461                result
462            }
463            .to_string()
464        );
465    }
466
467    #[test]
468    fn rename_create_empty() {
469        let mut builder = default_builder!();
470        builder.create_empty = Ident::new("empty", proc_macro2::Span::call_site());
471
472        assert_eq!(
473            quote!(#builder).to_string(),
474            {
475                let mut result = quote!();
476
477                #[cfg(not(feature = "clippy"))]
478                result.append_all(quote!(#[allow(clippy::all)]));
479
480                result.append_all(quote!(
481                    #[derive(Clone)]
482                    pub struct FooBuilder {
483                        foo: u32,
484                    }
485                ));
486
487                #[cfg(not(feature = "clippy"))]
488                result.append_all(quote!(#[allow(clippy::all)]));
489
490                result.append_all(quote!(
491                    #[allow(dead_code)]
492                    impl FooBuilder {
493                        fn bar () -> {
494                            unimplemented!()
495                        }
496
497                        /// Create an empty builder, with all fields set to `None` or `PhantomData`.
498                        fn empty() -> Self {
499                            Self {
500                                foo: ::derive_builder::export::core::default::Default::default(),
501                            }
502                        }
503                    }
504
505                    impl ::derive_builder::export::core::default::Default for FooBuilder {
506                        fn default() -> Self {
507                            Self::empty()
508                        }
509                    }
510                ));
511
512                add_generated_error(&mut result);
513
514                result
515            }
516            .to_string()
517        );
518    }
519
520    // This test depends on the exact formatting of the `stringify`'d code,
521    // so we don't automatically format the test
522    #[rustfmt::skip]
523    #[test]
524    fn generic() {
525        let ast: syn::DeriveInput = parse_quote! {
526            struct Lorem<'a, T: Debug> where T: PartialEq { }
527        };
528        let generics = ast.generics;
529        let mut builder = default_builder!();
530        builder.generics = Some(&generics);
531
532        assert_eq!(
533            quote!(#builder).to_string(),
534            {
535                let mut result = quote!();
536
537                #[cfg(not(feature = "clippy"))]
538                result.append_all(quote!(#[allow(clippy::all)]));
539
540                result.append_all(quote!(
541                    #[derive(Clone)]
542                    pub struct FooBuilder<'a, T: Debug> where T: PartialEq {
543                        foo: u32,
544                    }
545                ));
546
547                #[cfg(not(feature = "clippy"))]
548                result.append_all(quote!(#[allow(clippy::all)]));
549
550                result.append_all(quote!(
551                    #[allow(dead_code)]
552                    impl<'a, T: Debug + ::derive_builder::export::core::clone::Clone> FooBuilder<'a, T> where T: PartialEq {
553                        fn bar() -> {
554                            unimplemented!()
555                        }
556
557                        /// Create an empty builder, with all fields set to `None` or `PhantomData`.
558                        fn create_empty() -> Self {
559                            Self {
560                                foo: ::derive_builder::export::core::default::Default::default(),
561                            }
562                        }
563                    }
564
565                    impl<'a, T: Debug + ::derive_builder::export::core::clone::Clone> ::derive_builder::export::core::default::Default for FooBuilder<'a, T> where T: PartialEq {
566                        fn default() -> Self {
567                            Self::create_empty()
568                        }
569                    }
570                ));
571
572                add_generated_error(&mut result);
573
574                result
575            }.to_string()
576        );
577    }
578
579    // This test depends on the exact formatting of the `stringify`'d code,
580    // so we don't automatically format the test
581    #[rustfmt::skip]
582    #[test]
583    fn generic_reference() {
584        let ast: syn::DeriveInput = parse_quote! {
585            struct Lorem<'a, T: 'a + Default> where T: PartialEq{ }
586        };
587
588        let generics = ast.generics;
589        let mut builder = default_builder!();
590        builder.generics = Some(&generics);
591
592        assert_eq!(
593            quote!(#builder).to_string(),
594            {
595                let mut result = quote!();
596
597                #[cfg(not(feature = "clippy"))]
598                result.append_all(quote!(#[allow(clippy::all)]));
599
600                result.append_all(quote!(
601                    #[derive(Clone)]
602                    pub struct FooBuilder<'a, T: 'a + Default> where T: PartialEq {
603                        foo: u32,
604                    }
605                ));
606
607                #[cfg(not(feature = "clippy"))]
608                result.append_all(quote!(#[allow(clippy::all)]));
609
610                result.append_all(quote!(
611                    #[allow(dead_code)]
612                    impl<'a, T: 'a + Default + ::derive_builder::export::core::clone::Clone> FooBuilder<'a, T>
613                    where
614                        T: PartialEq
615                    {
616                        fn bar() -> {
617                            unimplemented!()
618                        }
619                        
620                        /// Create an empty builder, with all fields set to `None` or `PhantomData`.
621                        fn create_empty() -> Self {
622                            Self {
623                                foo: ::derive_builder::export::core::default::Default::default(),
624                            }
625                        }
626                    }
627
628                    impl<'a, T: 'a + Default + ::derive_builder::export::core::clone::Clone> ::derive_builder::export::core::default::Default for FooBuilder<'a, T> where T: PartialEq {
629                        fn default() -> Self {
630                            Self::create_empty()
631                        }
632                    }
633                ));
634
635                add_generated_error(&mut result);
636
637                result
638            }.to_string()
639        );
640    }
641
642    // This test depends on the exact formatting of the `stringify`'d code,
643    // so we don't automatically format the test
644    #[rustfmt::skip]
645    #[test]
646    fn owned_generic() {
647        let ast: syn::DeriveInput = parse_quote! {
648            struct Lorem<'a, T: Debug> where T: PartialEq { }
649        };
650        let generics = ast.generics;
651        let mut builder = default_builder!();
652        builder.generics = Some(&generics);
653        builder.pattern = BuilderPattern::Owned;
654        builder.must_derive_clone = false;
655
656        assert_eq!(
657            quote!(#builder).to_string(),
658            {
659                let mut result = quote!();
660
661                #[cfg(not(feature = "clippy"))]
662                result.append_all(quote!(#[allow(clippy::all)]));
663
664                result.append_all(quote!(
665                    pub struct FooBuilder<'a, T: Debug> where T: PartialEq {
666                        foo: u32,
667                    }
668                ));
669
670                #[cfg(not(feature = "clippy"))]
671                result.append_all(quote!(#[allow(clippy::all)]));
672
673                result.append_all(quote!(
674                    #[allow(dead_code)]
675                    impl<'a, T: Debug> FooBuilder<'a, T> where T: PartialEq {
676                        fn bar() -> {
677                            unimplemented!()
678                        }
679
680                        /// Create an empty builder, with all fields set to `None` or `PhantomData`.
681                        fn create_empty() -> Self {
682                            Self {
683                                foo: ::derive_builder::export::core::default::Default::default(),
684                            }
685                        }
686                    }
687
688                    impl<'a, T: Debug> ::derive_builder::export::core::default::Default for FooBuilder<'a, T>
689                    where T: PartialEq {
690                        fn default() -> Self {
691                            Self::create_empty()
692                        }
693                    }
694                ));
695
696                add_generated_error(&mut result);
697
698                result
699            }.to_string()
700        );
701    }
702
703    #[test]
704    fn disabled() {
705        let mut builder = default_builder!();
706        builder.enabled = false;
707
708        assert_eq!(quote!(#builder).to_string(), quote!().to_string());
709    }
710
711    #[test]
712    fn add_derives() {
713        let derives = vec![parse_quote!(Serialize)];
714        let mut builder = default_builder!();
715        builder.derives = &derives;
716
717        assert_eq!(
718            quote!(#builder).to_string(),
719            {
720                let mut result = quote!();
721
722                #[cfg(not(feature = "clippy"))]
723                result.append_all(quote!(#[allow(clippy::all)]));
724
725                result.append_all(quote!(
726                    #[derive(Clone, Serialize)]
727                    pub struct FooBuilder {
728                        foo: u32,
729                    }
730                ));
731
732                #[cfg(not(feature = "clippy"))]
733                result.append_all(quote!(#[allow(clippy::all)]));
734
735                result.append_all(quote!(
736                    #[allow(dead_code)]
737                    impl FooBuilder {
738                        fn bar () -> {
739                            unimplemented!()
740                        }
741
742                        /// Create an empty builder, with all fields set to `None` or `PhantomData`.
743                        fn create_empty() -> Self {
744                            Self {
745                                foo: ::derive_builder::export::core::default::Default::default(),
746                            }
747                        }
748                    }
749
750                    impl ::derive_builder::export::core::default::Default for FooBuilder {
751                        fn default() -> Self {
752                            Self::create_empty()
753                        }
754                    }
755                ));
756
757                add_generated_error(&mut result);
758
759                result
760            }
761            .to_string()
762        );
763    }
764}