netconf/message/rpc/operation/
copy_config.rs

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