-
-
Notifications
You must be signed in to change notification settings - Fork 868
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
camelCaserule, 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_allis needed. - Use ASCII field names and the
#[serde(rename = "项目名称")]attribute on each field individually. - Remove the
rename_allattribute 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.