-
-
Notifications
You must be signed in to change notification settings - Fork 857
Description
Hello Serde Team,
I've encountered a compile-time panic when using #[derive(Deserialize)]
in combination with #[serde(rename_all = "camelCase")]
on a struct that has fields with non-ASCII identifiers (specifically, Chinese characters).
Summary
The serde_derive
procedural macro appears to panic during compilation when it tries to apply the camelCase
renaming rule to a field name containing multi-byte UTF-8 characters. The error message clearly indicates a byte-indexing issue on a non-char boundary, suggesting the renaming logic might be incorrectly assuming ASCII strings.
The issue does not occur if:
- The
#[serde(rename_all = "camelCase")]
attribute is removed. - The attribute is changed to
#[serde(rename_all = "PascalCase")]
.
This suggests the bug is specific to the implementation of the camelCase
transformation logic.
Minimal Reproducible Example (MRE)
Here is the smallest possible Rust project that demonstrates the bug:
Cargo.toml
:
[package]
name = "serde-cjk-bug-report"
version = "0.1.0"
edition = "2024"
[dependencies]
serde = { version = "1.0.219", features = ["derive"] }
src/main.rs
:
use serde::Deserialize;
// This struct definition causes the compiler to panic.
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct TestPayload {
// Field name with Chinese characters
pub 项目名称: String,
pub 项目地址: String,
}
fn main() {
// The panic happens at compile time, so the main function's content
// doesn't matter, but it's here to make the example complete.
println!("This code will not compile.");
}
Compiler Panic Output
When trying to compile the MRE with cargo build
, the compiler panics with the following output:
error: proc-macro derive panicked
--> src/main.rs:5:10
|
5 | #[derive(Deserialize, Debug, Clone)]
| ^^^^^^^^^^^
|
= help: message: byte index 1 is not a char boundary; it is inside '项' (bytes 0..3) of `项目名称`
Expected vs. Actual Behavior
- Expected Behavior: The code should compile successfully. The
camelCase
rule, when applied to a field name like项目名称
which has no case or separators to modify, should ideally result in no change to the name, or at least not cause a panic. - Actual Behavior: The compiler panics with a fatal error related to string indexing.
Analysis
The panic message byte index 1 is not a char boundary
strongly suggests that the string manipulation logic within the rename_all = "camelCase"
implementation is incorrectly treating the UTF-8 field identifier as a sequence of bytes rather than characters. It attempts a byte-level index access, which is unsafe for multi-byte strings. A correct implementation should iterate over chars()
rather than bytes()
.
Workarounds
For others encountering this issue, the current workarounds are:
- Avoid using non-ASCII field names if
rename_all
is needed. - Use ASCII field names and the
#[serde(rename = "项目名称")]
attribute on each field individually. - Remove the
rename_all
attribute if the exact casing is not critical for your use case.
Environment
- Rust Version:
rustc 1.89.0 (29483883e 2025-08-04)
- Serde Version:
1.0.219
- OS: Windows 10
Thank you for maintaining this essential crate! I hope this report is helpful in resolving the issue.