Skip to content

Commit a29bfd7

Browse files
authored
Merge pull request #85 from Kriskras99/feat/field_override
feat: Allow to override (part of) the generated code for a field (no CLI support)
2 parents 79039e7 + 7d8725e commit a29bfd7

File tree

11 files changed

+321
-28
lines changed

11 files changed

+321
-28
lines changed

src/generator.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::{HashMap, VecDeque};
22
use std::fs;
33
use 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

77
use crate::Schema;
88
use 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

291297
impl 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+
341384
impl 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
}

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ mod generator;
55
mod templates;
66

77
pub use crate::error::{Error, Result};
8-
pub use crate::generator::{Generator, GeneratorBuilder, ImplementAvroSchema, Source};
8+
pub use crate::generator::{
9+
FieldOverride, Generator, GeneratorBuilder, ImplementAvroSchema, Source,
10+
};
911

1012
pub use apache_avro;
1113
pub use apache_avro::Schema;

0 commit comments

Comments
 (0)