clap_serde/
lib.rs

1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2#![doc  = include_str!("../README.md")]
3
4use clap::{Arg, ArgGroup, Command};
5use serde::Deserializer;
6use std::ops::Deref;
7
8#[cfg(not(any(
9    feature = "kebab-case-key",
10    feature = "snake-case-key",
11    feature = "pascal-case-key"
12)))]
13compile_error!("Case setting feature is missing. Either one should be set.");
14
15#[cfg(any(
16    all(feature = "kebab-case-key", feature = "snake-case-key"),
17    all(feature = "kebab-case-key", feature = "pascal-case-key"),
18    all(feature = "pascal-case-key", feature = "snake-case-key"),
19))]
20compile_error!("Case setting feature is conflicting. Only one should be set.");
21
22#[macro_use]
23mod de;
24#[cfg(feature = "docsrs")]
25pub mod documents;
26#[cfg(feature = "yaml")]
27#[deprecated(since = "0.4", note = "use serde-yaml instead")]
28mod yaml;
29
30#[cfg(all(test, feature = "snake-case-key"))]
31mod tests;
32
33#[cfg(feature = "yaml")]
34pub use yaml::{yaml_to_app, YamlWrap};
35
36/**
37Deserialize [`Command`] from [`Deserializer`].
38```
39const CLAP_TOML: &'static str = r#"
40name = "app_clap_serde"
41version = "1.0"
42author = "tester"
43about = "test-clap-serde"
44"#;
45let app = clap_serde::load(&mut toml::Deserializer::new(CLAP_TOML))
46    .expect("parse failed");
47assert_eq!(app.get_name(), "app_clap_serde");
48assert_eq!(app.get_about(), Some("test-clap-serde"));
49```
50*/
51pub fn load<'de, D>(de: D) -> Result<Command<'de>, D::Error>
52where
53    D: Deserializer<'de>,
54{
55    use serde::Deserialize;
56    CommandWrap::deserialize(de).map(|a| a.into())
57}
58
59/**
60Wrapper of [`Command`] to deserialize.
61```
62const CLAP_TOML: &'static str = r#"
63name = "app_clap_serde"
64version = "1.0"
65author = "tester"
66about = "test-clap-serde"
67"#;
68let app: clap::Command = toml::from_str::<clap_serde::CommandWrap>(CLAP_TOML)
69    .expect("parse failed")
70    .into();
71assert_eq!(app.get_name(), "app_clap_serde");
72assert_eq!(app.get_about(), Some("test-clap-serde"));
73```
74*/
75#[derive(Debug, Clone)]
76pub struct CommandWrap<'a> {
77    app: Command<'a>,
78}
79
80#[deprecated]
81pub type AppWrap<'a> = CommandWrap<'a>;
82
83impl<'a> From<CommandWrap<'a>> for Command<'a> {
84    fn from(a: CommandWrap<'a>) -> Self {
85        a.app
86    }
87}
88
89impl<'a> From<Command<'a>> for CommandWrap<'a> {
90    fn from(app: Command<'a>) -> Self {
91        CommandWrap { app }
92    }
93}
94
95impl<'a> Deref for CommandWrap<'a> {
96    type Target = Command<'a>;
97
98    fn deref(&self) -> &Self::Target {
99        &self.app
100    }
101}
102
103/// Wrapper of [`Arg`] to deserialize with [`DeserializeSeed`](`serde::de::DeserializeSeed`).
104#[derive(Debug, Clone)]
105pub struct ArgWrap<'a> {
106    arg: Arg<'a>,
107}
108
109impl<'a> From<ArgWrap<'a>> for Arg<'a> {
110    fn from(arg: ArgWrap<'a>) -> Self {
111        arg.arg
112    }
113}
114
115impl<'a> From<Arg<'a>> for ArgWrap<'a> {
116    fn from(arg: Arg<'a>) -> Self {
117        ArgWrap { arg }
118    }
119}
120
121impl<'a> Deref for ArgWrap<'a> {
122    type Target = Arg<'a>;
123
124    fn deref(&self) -> &Self::Target {
125        &self.arg
126    }
127}
128
129pub(crate) struct ArgGroupWrap<'a> {
130    group: ArgGroup<'a>,
131}
132
133impl<'a> From<ArgGroupWrap<'a>> for ArgGroup<'a> {
134    fn from(group: ArgGroupWrap<'a>) -> Self {
135        group.group
136    }
137}
138
139impl<'a> From<ArgGroup<'a>> for ArgGroupWrap<'a> {
140    fn from(group: ArgGroup<'a>) -> Self {
141        ArgGroupWrap { group }
142    }
143}