netconf/message/rpc/operation/
get_config.rs

1use std::{fmt::Debug, io::Write, marker::PhantomData};
2
3use quick_xml::Writer;
4
5use crate::{
6    capabilities::Requirements,
7    message::{ReadXml, WriteError},
8    session::Context,
9    Error,
10};
11
12use super::{params::Required, DataReply, Datastore, Filter, Operation, WriteXml};
13
14#[derive(Debug, Clone)]
15pub struct GetConfig<D> {
16    source: Datastore,
17    filter: Option<Filter>,
18    _reply: PhantomData<D>,
19}
20
21impl<D> Default for GetConfig<D> {
22    fn default() -> Self {
23        Self {
24            source: Datastore::default(),
25            filter: None,
26            _reply: PhantomData,
27        }
28    }
29}
30
31impl<D> Operation for GetConfig<D>
32where
33    D: ReadXml + Debug + Send + Sync,
34{
35    const NAME: &'static str = "get-config";
36    const REQUIRED_CAPABILITIES: Requirements = Requirements::None;
37
38    type Builder<'a> = Builder<'a>;
39    type Reply = DataReply<D>;
40}
41
42impl<D> WriteXml for GetConfig<D>
43where
44    D: ReadXml + Debug + Send + Sync,
45{
46    fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), WriteError> {
47        writer
48            .create_element(Self::NAME)
49            .write_inner_content(|writer| {
50                _ = writer
51                    .create_element("source")
52                    .write_inner_content(|writer| self.source.write_xml(writer))?;
53                if let Some(ref filter) = self.filter {
54                    filter.write_xml(writer)?;
55                };
56                Ok(())
57            })
58            .map(|_| ())
59    }
60}
61
62#[derive(Debug, Clone)]
63#[must_use]
64pub struct Builder<'a> {
65    ctx: &'a Context,
66    source: Required<Datastore>,
67    filter: Option<Filter>,
68}
69
70impl Builder<'_> {
71    pub fn source(mut self, source: Datastore) -> Result<Self, Error> {
72        source.try_as_source(self.ctx).map(|source| {
73            self.source.set(source);
74            self
75        })
76    }
77
78    pub fn filter(mut self, filter: Option<Filter>) -> Result<Self, Error> {
79        self.filter = filter.map(|filter| filter.try_use(self.ctx)).transpose()?;
80        Ok(self)
81    }
82}
83
84impl<'a, D> super::Builder<'a, GetConfig<D>> for Builder<'a>
85where
86    D: ReadXml + Debug + Send + Sync,
87{
88    fn new(ctx: &'a Context) -> Self {
89        Self {
90            ctx,
91            source: Required::init(),
92            filter: None,
93        }
94    }
95
96    fn finish(self) -> Result<GetConfig<D>, Error> {
97        Ok(GetConfig {
98            source: self.source.require::<GetConfig<D>>("source")?,
99            filter: self.filter,
100            _reply: PhantomData,
101        })
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use crate::message::{
109        rpc::{operation::Opaque, MessageId, Request},
110        ClientMsg,
111    };
112
113    #[test]
114    fn default_request_to_xml() {
115        let req: Request<GetConfig<Opaque>> = Request {
116            message_id: MessageId(101),
117            operation: GetConfig::default(),
118        };
119        let expect = r#"<rpc message-id="101"><get-config><source><running/></source></get-config></rpc>]]>]]>"#;
120        assert_eq!(req.to_xml().unwrap(), expect);
121    }
122}