From 1799c064ad12a4fb8d181e8566ce32629d1ad70d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 28 May 2026 21:41:07 -0700 Subject: [PATCH] update docs --- src/de.rs | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/se.rs | 2 ++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/de.rs b/src/de.rs index 9b51d83..a1f9fd0 100644 --- a/src/de.rs +++ b/src/de.rs @@ -2,6 +2,16 @@ //! //! This module provides [`from_str`] for deserializing Rust types from KDL text. //! +//! Due to the fact that `serde` was developed with JSON in mind, and the incompatibility +//! between KDL and JSON's data model, not all `serde` concepts apply smoothly to KDL. This +//! leads to the fact that some KDL concepts are inexpressible in terms of `serde` derives +//! and may require manual deserialization. +//! +//! The most notable restriction is the ability to distinguish between *arguments*, +//! *properties* and *child nodes*, as JSON does not have such conception. +//! +//! Due to that the mapping is performed in a best effort manner. +//! //! # KDL → Serde Data Model Mapping //! //! KDL documents are mapped to serde's data model as follows: @@ -29,13 +39,97 @@ //! } //! //! let kdl = r#" -//! name "my-app" +//! name my-app //! port 8080 //! "#; //! //! let config: Config = kdl::de::from_str(kdl).unwrap(); //! assert_eq!(config, Config { name: "my-app".into(), port: 8080 }); //! ``` +//! +//! ## Arguments mapping +//! +//! This library supports two kinds of special renaming for arguments - `#{n}` and `#args`: +//! +//! - `#{n}`: This is used when you want to access argument at a specific +//! position. The field name should start with `#`, then follow by the position +//! of the argument in numerical order starting from 0. +//! +//! ```rust +//! use serde::Deserialize; +//! +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct Config { +//! server: Server, +//! } +//! +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct Server { +//! #[serde(rename = "#0")] +//! name: String, +//! #[serde(rename = "#1")] +//! port: u16, +//! } +//! +//! let kdl = r#" +//! server my-app 8080 +//! "#; +//! +//! let config: Config = kdl::de::from_str(kdl).unwrap(); +//! assert_eq!(config, Config { server: Server { name: "my-app".into(), port: 8080 }}); +//! ``` +//! +//! - `#args`: This is used when you want to collect *all* the arguments of the node. +//! +//! ```rust +//! use serde::Deserialize; +//! +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct Config { +//! server: Server, +//! } +//! +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct Server { +//! #[serde(rename = "#args")] +//! info: Vec, +//! } +//! +//! let kdl = r#" +//! server my-app "https://example.com" +//! "#; +//! +//! let config: Config = kdl::de::from_str(kdl).unwrap(); +//! assert_eq!(config, Config { server: Server { info: Vec::from(["my-app".into(), "https://example.com".into()]) }}); +//! ``` +//! +//! ## Properties mapping +//! +//! You can use `#@field-name` on a field that will be used for a property. +//! +//! ```rust +//! use serde::Deserialize; +//! +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct Config { +//! server: Server, +//! } +//! +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct Server { +//! #[serde(rename = "#0")] +//! name: String, +//! #[serde(rename = "#@port")] +//! port: u16, +//! } +//! +//! let kdl = r#" +//! server my-app port=8080 +//! "#; +//! +//! let config: Config = kdl::de::from_str(kdl).unwrap(); +//! assert_eq!(config, Config { server: Server { name: "my-app".into(), port: 8080 }}); +//! ``` use std::borrow::Cow; use std::fmt; @@ -95,7 +189,7 @@ fn str_deserializer(s: &str) -> de::value::StrDeserializer<'_, Error> { /// } /// /// let kdl = r#" -/// name "my-app" +/// name my-app /// port 8080 /// "#; /// diff --git a/src/se.rs b/src/se.rs index 89abf34..b882033 100644 --- a/src/se.rs +++ b/src/se.rs @@ -30,6 +30,8 @@ //! let kdl = kdl::se::to_string(&config).unwrap(); //! assert_eq!(kdl, "name my-app\nport 8080\n"); //! ``` +//! You can refer to the [crate::de] module to further customize the +//! (de)serialization model. use serde::ser::{self, Serialize}; use std::fmt;