mod break_the_archive;
mod dm;
mod process_upload;
pub use break_the_archive::BreakTheArchive;
pub use dm::Dm;
pub use process_upload::ProcessUpload;
#[cfg(feature = "serde")]
use ::serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
use crate::control::de;
#[derive(Clone, Debug)]
pub struct Command {
pub header: CommandHeader,
pub actions: Vec<CommandAction>,
}
#[derive(Debug)]
#[cfg_attr(not(feature = "serde"), allow(missing_copy_implementations))]
pub enum CommandError {
#[cfg(feature = "serde")]
De(de::Error),
}
#[cfg(feature = "serde")]
impl From<de::Error> for CommandError {
fn from(dee: de::Error) -> Self {
Self::De(dee)
}
}
crate::errors::error_enum!(CommandError);
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(feature = "serde", serde(tag = "Action"))]
pub enum CommandAction {
Dm(Dm),
#[cfg_attr(feature = "serde", serde(rename = "break-the-archive"))]
BreakTheArchive(BreakTheArchive),
#[cfg_attr(feature = "serde", serde(rename = "process-upload"))]
ProcessUpload(ProcessUpload),
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "PascalCase"))]
pub struct CommandHeader {
pub archive: String,
pub uploader: Option<String>,
}
#[cfg(feature = "serde")]
mod _serde {
#![cfg_attr(docsrs, doc(cfg(feature = "serde")))]
use super::*;
use std::io::{BufReader, Read};
impl Command {
pub fn from_reader<ReadT>(read: &mut BufReader<ReadT>) -> Result<Command, CommandError>
where
ReadT: Read,
{
let header: CommandHeader = de::from_reader(read)?;
Ok(Command {
header,
actions: de::from_reader_iter(read).collect::<Result<Vec<_>, _>>()?,
})
}
}
#[cfg(feature = "tokio")]
mod _tokio {
#![cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
use super::*;
use crate::control::de;
use tokio::io::{AsyncRead, BufReader};
impl Command {
pub async fn from_reader_async<ReadT>(
read: &mut BufReader<ReadT>,
) -> Result<Command, CommandError>
where
ReadT: AsyncRead,
ReadT: Unpin,
{
let header: CommandHeader = de::from_reader_async(read).await?;
let mut actions = vec![];
while let Some(action) = de::from_reader_async_iter(read).next().await {
let action = action?;
actions.push(action);
}
Ok(Command { header, actions })
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[tokio::test]
async fn command() {
let command = Command::from_reader_async(&mut BufReader::new(Cursor::new(
"\
Archive: ftp.upload.debian.org
Uploader: Paul Tagliamonte <paultag@debian.org>
Action: dm
Fingerprint: 1234567890ABCDEF1234567890ABCDEF
Allow: one-package another-package
Deny: yet-another-package
Action: dm
Fingerprint: 1234567890ABCDEF1234567890ABCDEF
Allow: one
Deny: two
",
)))
.await
.unwrap();
assert_eq!(command.header.archive, "ftp.upload.debian.org");
assert_eq!(2, command.actions.len());
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::control::de;
use std::io::Cursor;
#[test]
fn command_dm() {
let command: CommandAction = de::from_str(
"\
Action: dm
Fingerprint: 1234567890ABCDEF1234567890ABCDEF
Allow: one-package another-package
Deny: yet-another-package
",
)
.unwrap();
let CommandAction::Dm(dm) = command else {
panic!("not a dm command");
};
assert_eq!("1234567890ABCDEF1234567890ABCDEF", &*dm.fingerprint);
assert_eq!(&["one-package", "another-package"], &*dm.allow.unwrap());
assert_eq!(&["yet-another-package"], &*dm.deny.unwrap());
}
#[test]
fn command_header() {
let header: CommandHeader = de::from_str(
"\
Archive: ftp.upload.debian.org
Uploader: Paul Tagliamonte <paultag@debian.org>
",
)
.unwrap();
assert_eq!("ftp.upload.debian.org", &header.archive);
assert_eq!(
"Paul Tagliamonte <paultag@debian.org>",
header.uploader.unwrap()
);
}
#[test]
fn command() {
let command = Command::from_reader(&mut BufReader::new(Cursor::new(
"\
Archive: ftp.upload.debian.org
Uploader: Paul Tagliamonte <paultag@debian.org>
Action: dm
Fingerprint: 1234567890ABCDEF1234567890ABCDEF
Allow: one-package another-package
Deny: yet-another-package
Action: dm
Fingerprint: 1234567890ABCDEF1234567890ABCDEF
Allow: one
Deny: two
",
)))
.unwrap();
assert_eq!(command.header.archive, "ftp.upload.debian.org");
assert_eq!(2, command.actions.len());
}
}
}