diff --git a/README.md b/README.md index f82b555b..e044bd53 100644 --- a/README.md +++ b/README.md @@ -571,6 +571,7 @@ In addition, it supports the following custom containers: - `rfl::Binary`: Used to express numbers in binary format. - `rfl::Box`: Similar to `std::unique_ptr`, but (almost) guaranteed to never be null. - `rfl::Bytestring`: An alias for `std::vector`. Supported by Avro, BSON, Cap'n Proto, CBOR, flexbuffers, msgpack and UBJSON. +- `rfl::Commented`: Allows you to add comments to fields (supported by YAML and XML). - `rfl::Generic`: A catch-all type that can represent (almost) anything. - `rfl::Hex`: Used to express numbers in hex format. - `rfl::Literal`: An explicitly enumerated string. diff --git a/docs/commented.md b/docs/commented.md new file mode 100644 index 00000000..494bceee --- /dev/null +++ b/docs/commented.md @@ -0,0 +1,81 @@ +# `rfl::Commented` + +The `rfl::Commented` wrapper allows you to add comments to fields in your structs. These comments are then serialized in formats that support them, such as YAML and XML. + +Note that `rfl::Commented` is currently unsupported by formats that do not have a standard way of representing comments, such as JSON. Also note that comments are **write-only**: they are ignored during deserialization. + +## Example (YAML) + +In YAML, the comments are added as line comments (`#`): + +```cpp +struct Person { + std::string first_name; + std::string last_name; + rfl::Commented town; +}; + +const auto homer = Person{.first_name = "Homer", + .last_name = "Simpson", + .town = rfl::Commented( + "Springfield", "The town where Homer lives")}; + +const auto yaml_str = rfl::yaml::write(homer); +``` + +This will result in the following YAML: + +```yaml +first_name: Homer +last_name: Simpson +town: Springfield # The town where Homer lives +``` + +## Example (XML) + +In XML, the comments are added as `` blocks after the field: + +```cpp +struct Person { + std::string first_name; + std::string last_name; + rfl::Commented town; +}; + +const auto homer = Person{.first_name = "Homer", + .last_name = "Simpson", + .town = rfl::Commented( + "Springfield", "The town where Homer lives")}; + +const auto xml_str = rfl::xml::write(homer); +``` + +This will result in the following XML: + +```xml + + + Homer + Simpson + Springfield + + +``` + +## API convenience + +`rfl::Commented` provides several ways to access and modify the underlying value and the comment: + +- `.get()`, `.value()`, `operator()()` — access the underlying value (const and non-const overloads). +- `.comment()` — returns an `std::optional` containing the comment. +- `.add_comment(std::string)` — sets or updates the comment. +- `.set(...)`, `operator=(...)` — assign the underlying value. + +Example: + +```cpp +Person p; +p.town = "Springfield"; +p.town.add_comment("The town where Homer lives"); +std::string s = p.town.value(); +``` diff --git a/mkdocs.yaml b/mkdocs.yaml index 988c1339..24e7e1fd 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -123,6 +123,7 @@ nav: - rfl::Box and rfl::Ref: rfl_ref.md - rfl::Timestamp: timestamps.md - rfl::Skip: rfl_skip.md + - rfl::Commented: commented.md - rfl::Result: result.md - Standard containers: standard_containers.md - C arrays and inheritance: c_arrays_and_inheritance.md