use std::io::Write;
use quick_xml::{events::BytesText, Writer};
use crate::{
capabilities::{Capability, Requirements},
message::WriteError,
session::Context,
Error,
};
use super::{EmptyReply, Operation, Token, WriteXml};
#[derive(Debug, Clone)]
pub struct CancelCommit {
persist_id: Option<Token>,
}
impl Operation for CancelCommit {
const NAME: &'static str = "cancel-commit";
const REQUIRED_CAPABILITIES: Requirements = Requirements::One(Capability::ConfirmedCommitV1_1);
type Builder<'a> = Builder<'a>;
type Reply = EmptyReply;
}
impl WriteXml for CancelCommit {
fn write_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), WriteError> {
let elem = writer.create_element("cancel-commit");
if let Some(ref token) = self.persist_id {
_ = elem.write_inner_content(|writer| {
writer
.create_element("persist-id")
.write_text_content(BytesText::new(&token.to_string()))
.map(|_| ())
})?;
} else {
_ = elem.write_empty()?;
};
Ok(())
}
}
#[derive(Debug, Clone)]
#[must_use]
pub struct Builder<'a> {
ctx: &'a Context,
persist_id: Option<Token>,
}
impl Builder<'_> {
pub fn persist_id(mut self, token: Option<Token>) -> Result<Self, Error> {
let required_capabilities = Requirements::One(Capability::ConfirmedCommitV1_1);
if required_capabilities.check(self.ctx.server_capabilities()) {
self.persist_id = token;
Ok(self)
} else {
Err(Error::UnsupportedOperationParameter {
operation_name: CancelCommit::NAME,
param_name: "persist-id",
required_capabilities,
})
}
}
}
impl<'a> super::Builder<'a, CancelCommit> for Builder<'a> {
fn new(ctx: &'a Context) -> Self {
Self {
ctx,
persist_id: None,
}
}
fn finish(self) -> Result<CancelCommit, Error> {
Ok(CancelCommit {
persist_id: self.persist_id,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::message::{
rpc::{MessageId, Request},
ClientMsg,
};
#[test]
fn non_persisted_request_to_xml() {
let req = Request {
message_id: MessageId(101),
operation: CancelCommit { persist_id: None },
};
let expect = r#"<rpc message-id="101"><cancel-commit/></rpc>]]>]]>"#;
assert_eq!(req.to_xml().unwrap(), expect);
}
#[test]
fn persisted_request_to_xml() {
let token = Token::generate();
let req = Request {
message_id: MessageId(101),
operation: CancelCommit {
persist_id: Some(token.clone()),
},
};
let expect = format!(
r#"<rpc message-id="101"><cancel-commit><persist-id>{token}</persist-id></cancel-commit></rpc>]]>]]>"#
);
assert_eq!(req.to_xml().unwrap(), expect);
}
}