This is an automated email from the ASF dual-hosted git repository. Kriskras99 pushed a commit to branch fix/remote in repository https://gitbox.apache.org/repos/asf/avro-rs.git
commit 00249ae47fecddc2be55b0440a825171f6afd94e Author: Kriskras99 <[email protected]> AuthorDate: Mon Jun 22 21:56:22 2026 +0200 fix: Enable `#[serde(remote = "..")]` support --- avro_derive/src/attributes/mod.rs | 14 ------ avro_derive/src/attributes/serde.rs | 9 ++-- avro_derive/tests/serde.rs | 68 ++++++++++++++++++++++++++ avro_derive/tests/ui/avro_rs_373_remote.rs | 33 ------------- avro_derive/tests/ui/avro_rs_373_remote.stderr | 9 ---- 5 files changed, 74 insertions(+), 59 deletions(-) diff --git a/avro_derive/src/attributes/mod.rs b/avro_derive/src/attributes/mod.rs index ebb2997..e68bbbb 100644 --- a/avro_derive/src/attributes/mod.rs +++ b/avro_derive/src/attributes/mod.rs @@ -63,12 +63,6 @@ impl NamedTypeOptions { "AvroSchema derive does not support changing the tagging Serde generates (`tag`, `content`, `untagged`, `variant_identifier`, `field_identifier`)", )); } - if serde.remote.is_some() { - errors.push(syn::Error::new( - span, - "AvroSchema derive does not support the Serde `remote` attribute", - )); - } if serde.rename_all.deserialize != serde.rename_all.serialize { errors.push(syn::Error::new( span, @@ -284,14 +278,6 @@ impl FieldOptions { // Collect errors so user gets all feedback at once let mut errors = Vec::new(); - // Check for any Serde attributes that are hard errors - if serde.getter.is_some() { - errors.push(syn::Error::new( - span, - "AvroSchema derive does not support the Serde `getter` attribute", - )); - } - // Check for conflicts between Serde and Avro if avro.skip && !(serde.skip || (serde.skip_serializing && serde.skip_deserializing)) { errors.push(syn::Error::new( diff --git a/avro_derive/src/attributes/serde.rs b/avro_derive/src/attributes/serde.rs index b1ca6fa..4f808ce 100644 --- a/avro_derive/src/attributes/serde.rs +++ b/avro_derive/src/attributes/serde.rs @@ -117,8 +117,10 @@ pub struct ContainerAttributes { pub _default: Option<SerdeDefault>, /// This type is the serde implementation for a "remote" type. /// - /// This makes the (de)serialisation use/return a different type. - pub remote: Option<String>, + /// This makes the (de)serialisation use/return a different type. However, the this type should + /// match the other type so the schema we generate is correct. + #[darling(rename = "remote")] + pub _remote: Option<String>, /// Directly use the inner type for (de)serialisation. #[darling(default)] pub transparent: bool, @@ -243,7 +245,8 @@ pub struct FieldAttributes { #[darling(rename = "borrow")] pub _borrow: Option<SerdeBorrow>, /// Used for remote types. - pub getter: Option<String>, + #[darling(rename = "getter")] + pub _getter: Option<String>, } #[cfg(test)] diff --git a/avro_derive/tests/serde.rs b/avro_derive/tests/serde.rs index 128fede..561e31e 100644 --- a/avro_derive/tests/serde.rs +++ b/avro_derive/tests/serde.rs @@ -370,6 +370,74 @@ mod container_attributes { a: vec!["spam".to_string()], }); } + + #[test] + fn avro_rs_562_remote() { + // The types and supporting code here have been pulled directly from the Serde documentation + // (https://serde.rs/remote-derive.html) + + // Pretend that this is somebody else's crate, not a module. + mod other_crate { + // Neither Serde nor the other crate provides Serialize and Deserialize + // impls for this struct. Oh, and the fields are private. + #[derive(Debug, PartialEq, Eq)] + pub struct Duration { + secs: i64, + nanos: i32, + } + + impl Duration { + pub fn new(secs: i64, nanos: i32) -> Self { + Duration { secs, nanos } + } + + pub fn seconds(&self) -> i64 { + self.secs + } + + pub fn subsec_nanos(&self) -> i32 { + self.nanos + } + } + } + + //////////////////////////////////////////////////////////////////////////////// + + use other_crate::Duration; + use serde::{Deserialize, Serialize}; + + // Provide getters for every private field of the remote struct. The getter must + // return either `T` or `&T` where `T` is the type of the field. + #[derive(Serialize, Deserialize, AvroSchema)] + #[serde(remote = "Duration")] + struct DurationDef { + #[serde(getter = "Duration::seconds")] + secs: i64, + #[serde(getter = "Duration::subsec_nanos")] + nanos: i32, + } + + // Provide a conversion to construct the remote type. + impl From<DurationDef> for Duration { + fn from(def: DurationDef) -> Duration { + Duration::new(def.secs, def.nanos) + } + } + + #[derive(Serialize, Deserialize, AvroSchema, Debug, PartialEq, Eq)] + struct Process { + command_line: String, + + #[serde(with = "DurationDef")] + #[avro(with)] + wall_time: Duration, + } + + serde_assert(Process { + command_line: "abracadabra".to_string(), + wall_time: Duration::new(15, 42), + }); + } } mod variant_attributes { diff --git a/avro_derive/tests/ui/avro_rs_373_remote.rs b/avro_derive/tests/ui/avro_rs_373_remote.rs deleted file mode 100644 index b6029c8..0000000 --- a/avro_derive/tests/ui/avro_rs_373_remote.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -use apache_avro::AvroSchema; - -#[derive(AvroSchema)] -struct Foo { - a: String, - b: i32, -} - -#[derive(AvroSchema)] -#[serde(remote = "Foo")] -struct FooRemote { - a: String, - b: i32, -} - -pub fn main() {} diff --git a/avro_derive/tests/ui/avro_rs_373_remote.stderr b/avro_derive/tests/ui/avro_rs_373_remote.stderr deleted file mode 100644 index fe4fd10..0000000 --- a/avro_derive/tests/ui/avro_rs_373_remote.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error: AvroSchema derive does not support the Serde `remote` attribute - --> tests/ui/avro_rs_373_remote.rs:27:1 - | -27 | / #[serde(remote = "Foo")] -28 | | struct FooRemote { -29 | | a: String, -30 | | b: i32, -31 | | } - | |_^
