netconf/message/rpc/operation/
lock.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, WriteXml};
8
9#[derive(Debug, Clone, Copy)]
10pub struct Lock {
11    target: Datastore,
12}
13
14impl Operation for Lock {
15    const NAME: &'static str = "lock";
16    const REQUIRED_CAPABILITIES: Requirements = Requirements::None;
17
18    type Builder<'a> = Builder<'a>;
19    type Reply = EmptyReply;
20}
21
22impl WriteXml for Lock {
23    fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), WriteError> {
24        writer
25            .create_element(Self::NAME)
26            .write_inner_content(|writer| {
27                writer
28                    .create_element("target")
29                    .write_inner_content(|writer| self.target.write_xml(writer))
30                    .map(|_| ())
31            })
32            .map(|_| ())
33    }
34}
35
36#[derive(Debug, Clone, Copy)]
37pub struct Unlock {
38    target: Datastore,
39}
40
41impl Operation for Unlock {
42    const NAME: &'static str = "unlock";
43    const REQUIRED_CAPABILITIES: Requirements = Requirements::None;
44
45    type Builder<'a> = Builder<'a>;
46    type Reply = EmptyReply;
47}
48
49impl WriteXml for Unlock {
50    fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), WriteError> {
51        writer
52            .create_element(Self::NAME)
53            .write_inner_content(|writer| {
54                writer
55                    .create_element("target")
56                    .write_inner_content(|writer| self.target.write_xml(writer))
57                    .map(|_| ())
58            })
59            .map(|_| ())
60    }
61}
62
63#[derive(Debug, Clone)]
64#[must_use]
65pub struct Builder<'a> {
66    ctx: &'a Context,
67    target: Required<Datastore>,
68}
69
70impl<'a> Builder<'a> {
71    const fn new(ctx: &'a Context) -> Self {
72        Self {
73            ctx,
74            target: Required::init(),
75        }
76    }
77
78    pub fn target(mut self, target: Datastore) -> Result<Self, Error> {
79        target.try_as_lock_target(self.ctx).map(|target| {
80            self.target.set(target);
81            self
82        })
83    }
84}
85
86impl<'a> super::Builder<'a, Lock> for Builder<'a> {
87    fn new(ctx: &'a Context) -> Self {
88        Self::new(ctx)
89    }
90
91    fn finish(self) -> Result<Lock, Error> {
92        Ok(Lock {
93            target: self.target.require::<Lock>("target")?,
94        })
95    }
96}
97
98impl<'a> super::Builder<'a, Unlock> for Builder<'a> {
99    fn new(ctx: &'a Context) -> Self {
100        Self::new(ctx)
101    }
102
103    fn finish(self) -> Result<Unlock, Error> {
104        Ok(Unlock {
105            target: self.target.require::<Unlock>("target")?,
106        })
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113    use crate::message::{
114        rpc::{MessageId, Request},
115        ClientMsg,
116    };
117
118    #[test]
119    fn lock_request_to_xml() {
120        let req = Request {
121            message_id: MessageId(101),
122            operation: Lock {
123                target: Datastore::Running,
124            },
125        };
126        let expect =
127            r#"<rpc message-id="101"><lock><target><running/></target></lock></rpc>]]>]]>"#;
128        assert_eq!(req.to_xml().unwrap(), expect);
129    }
130
131    #[test]
132    fn unlock_request_to_xml() {
133        let req = Request {
134            message_id: MessageId(101),
135            operation: Unlock {
136                target: Datastore::Running,
137            },
138        };
139        let expect =
140            r#"<rpc message-id="101"><unlock><target><running/></target></unlock></rpc>]]>]]>"#;
141        assert_eq!(req.to_xml().unwrap(), expect);
142    }
143}