@@ -2,7 +2,7 @@ use std::collections::{HashMap, VecDeque};
22use std:: fs;
33use std:: io:: prelude:: * ;
44
5- use apache_avro:: schema:: { ArraySchema , DecimalSchema , MapSchema , RecordField , RecordSchema } ;
5+ use apache_avro:: schema:: { ArraySchema , DecimalSchema , MapSchema , Name , RecordField , RecordSchema } ;
66
77use crate :: Schema ;
88use crate :: error:: { Error , Result } ;
@@ -88,6 +88,11 @@ impl Generator {
8888 fn gen_in_order ( & self , deps : & mut Vec < Schema > , output : & mut impl Write ) -> Result < ( ) > {
8989 let mut gs = GenState :: new ( deps) ?. with_chrono_dates ( self . templater . use_chrono_dates ) ;
9090
91+ if !self . templater . field_overrides . is_empty ( ) {
92+ // This rechecks no_eq for all schemas, so only do it if there are actually overrides.
93+ gs = gs. with_field_overrides ( deps, & self . templater . field_overrides ) ?;
94+ }
95+
9196 while let Some ( s) = deps. pop ( ) {
9297 match s {
9398 // Simply generate code
@@ -286,6 +291,7 @@ pub struct GeneratorBuilder {
286291 derive_builders : bool ,
287292 impl_schemas : ImplementAvroSchema ,
288293 extra_derives : Vec < String > ,
294+ field_overrides : HashMap < Name , Vec < FieldOverride > > ,
289295}
290296
291297impl Default for GeneratorBuilder {
@@ -298,6 +304,7 @@ impl Default for GeneratorBuilder {
298304 derive_builders : false ,
299305 impl_schemas : ImplementAvroSchema :: None ,
300306 extra_derives : vec ! [ ] ,
307+ field_overrides : HashMap :: new ( ) ,
301308 }
302309 }
303310}
@@ -338,6 +345,42 @@ impl std::fmt::Display for ImplementAvroSchema {
338345 }
339346}
340347
348+ /// Override (part of) the generated code for a [`Schema`] field.
349+ ///
350+ /// Currently only possible for Record schemas.
351+ ///
352+ /// When changing the type of the field, `implements_eq` must also be changed.
353+ /// `serde_with` and `default` might also need to be changed. If this is not done
354+ /// it will result in a compiler error.
355+ #[ derive( Debug , Clone ) ]
356+
357+ pub struct FieldOverride {
358+ /// Name of the schema the field is in.
359+ pub schema : Name ,
360+ /// Name of the field as in the schema.
361+ pub field : String ,
362+ /// Change the documentation of the field.
363+ pub docstring : Option < String > ,
364+ /// Change the type of the field.
365+ ///
366+ /// This type *must* implement [`Debug`], [`PartialEq`], and [`Clone`].
367+ /// If extra derives are configured (including `Builder` and [`AvroSchema`](apache_avro::AvroSchema))
368+ /// then the type *must* also implement these.
369+ pub type_name : Option < String > ,
370+ /// Does the type implement [`Eq`].
371+ ///
372+ /// This *must* be set if the type is changed.
373+ pub implements_eq : Option < bool > ,
374+ /// Module name to use for `#[serde(with = ...)]`.
375+ ///
376+ /// This *must* be set if the type was changed and the type does not implement `Serialize` or `Deserialize`.
377+ pub serde_with : Option < String > ,
378+ /// Default value for this field, can be a function call that generates the default value.
379+ ///
380+ /// This *must* be set if the field is nullable and the type was changed and the outer type is not an [`Option`].
381+ pub default : Option < String > ,
382+ }
383+
341384impl GeneratorBuilder {
342385 /// Creates a new [`GeneratorBuilder`](GeneratorBuilder).
343386 pub fn new ( ) -> GeneratorBuilder {
@@ -402,6 +445,30 @@ impl GeneratorBuilder {
402445 self
403446 }
404447
448+ /// Override (part of) the code generated for a field.
449+ ///
450+ /// Applies to record structs.
451+ pub fn override_fields ( mut self , overrides : Vec < FieldOverride > ) -> GeneratorBuilder {
452+ for over in overrides {
453+ self . field_overrides
454+ . entry ( over. schema . clone ( ) )
455+ . or_default ( )
456+ . push ( over) ;
457+ }
458+ self
459+ }
460+
461+ /// Override (part of) the code generated for a field.
462+ ///
463+ /// Applies to record structs.
464+ pub fn override_field ( mut self , over : FieldOverride ) -> GeneratorBuilder {
465+ self . field_overrides
466+ . entry ( over. schema . clone ( ) )
467+ . or_default ( )
468+ . push ( over) ;
469+ self
470+ }
471+
405472 /// Create a [`Generator`](Generator) with the builder parameters.
406473 pub fn build ( self ) -> Result < Generator > {
407474 let mut templater = Templater :: new ( ) ?;
@@ -413,6 +480,7 @@ impl GeneratorBuilder {
413480 templater. derive_schemas = self . impl_schemas == ImplementAvroSchema :: Derive ;
414481 templater. impl_schemas = self . impl_schemas == ImplementAvroSchema :: CopyBuildSchema ;
415482 templater. extra_derives = self . extra_derives ;
483+ templater. field_overrides = self . field_overrides ;
416484 Ok ( Generator { templater } )
417485 }
418486}
0 commit comments