Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
139 lines
4.4 KiB
Rust
139 lines
4.4 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use super::{ImapResponse, capability::QuotaResourceName, quoted_string};
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct Arguments {
|
|
pub tag: String,
|
|
pub name: String,
|
|
}
|
|
|
|
pub struct QuotaItem {
|
|
pub name: String,
|
|
pub resources: Vec<QuotaResource>,
|
|
}
|
|
|
|
pub struct QuotaResource {
|
|
pub resource: QuotaResourceName,
|
|
pub total: u64,
|
|
pub used: u64,
|
|
}
|
|
|
|
pub struct Response {
|
|
pub quota_root_items: Vec<String>,
|
|
pub quota_items: Vec<QuotaItem>,
|
|
}
|
|
|
|
impl ImapResponse for Response {
|
|
fn serialize(self) -> Vec<u8> {
|
|
let mut buf = Vec::with_capacity(64);
|
|
if !self.quota_root_items.is_empty() {
|
|
buf.extend_from_slice(b"* QUOTAROOT");
|
|
for item in &self.quota_root_items {
|
|
buf.push(b' ');
|
|
quoted_string(&mut buf, item);
|
|
}
|
|
buf.extend_from_slice(b"\r\n");
|
|
}
|
|
|
|
if !self.quota_items.is_empty() {
|
|
for item in &self.quota_items {
|
|
buf.extend_from_slice(b"* QUOTA ");
|
|
quoted_string(&mut buf, &item.name);
|
|
buf.extend_from_slice(b" (");
|
|
for (pos, resource) in item.resources.iter().enumerate() {
|
|
if pos > 0 {
|
|
buf.push(b' ');
|
|
}
|
|
|
|
let mut total = resource.total;
|
|
let mut used = resource.used;
|
|
|
|
match resource.resource {
|
|
QuotaResourceName::Storage => {
|
|
total /= 1024;
|
|
used /= 1024;
|
|
|
|
buf.extend_from_slice(b"STORAGE ")
|
|
}
|
|
QuotaResourceName::Message => buf.extend_from_slice(b"MESSAGE "),
|
|
QuotaResourceName::Mailbox => buf.extend_from_slice(b"MAILBOX "),
|
|
QuotaResourceName::AnnotationStorage => {
|
|
buf.extend_from_slice(b"ANNOTATION-STORAGE ")
|
|
}
|
|
}
|
|
|
|
buf.extend_from_slice(format!("{used} {total}").as_bytes());
|
|
}
|
|
buf.extend_from_slice(b")\r\n");
|
|
}
|
|
}
|
|
|
|
buf
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::protocol::{ImapResponse, capability::QuotaResourceName};
|
|
|
|
use super::{QuotaItem, QuotaResource};
|
|
|
|
#[test]
|
|
fn serialize_quota() {
|
|
for (response, expected) in [
|
|
(
|
|
super::Response {
|
|
quota_root_items: vec!["INBOX".into(), "#test".into()],
|
|
quota_items: vec![],
|
|
},
|
|
"* QUOTAROOT \"INBOX\" \"#test\"\r\n",
|
|
),
|
|
(
|
|
super::Response {
|
|
quota_root_items: vec![],
|
|
quota_items: vec![QuotaItem {
|
|
name: "INBOX".into(),
|
|
resources: vec![QuotaResource {
|
|
resource: QuotaResourceName::Storage,
|
|
total: 1073741824,
|
|
used: 1048576,
|
|
}],
|
|
}],
|
|
},
|
|
"* QUOTA \"INBOX\" (STORAGE 1024 1048576)\r\n",
|
|
),
|
|
(
|
|
super::Response {
|
|
quota_root_items: vec!["my mailbox".into(), "".into()],
|
|
quota_items: vec![QuotaItem {
|
|
name: "INBOX".into(),
|
|
resources: vec![
|
|
QuotaResource {
|
|
resource: QuotaResourceName::Storage,
|
|
total: 1073741824,
|
|
used: 1048576,
|
|
},
|
|
QuotaResource {
|
|
resource: QuotaResourceName::Message,
|
|
total: 100,
|
|
used: 2,
|
|
},
|
|
],
|
|
}],
|
|
},
|
|
concat!(
|
|
"* QUOTAROOT \"my mailbox\" \"\"\r\n",
|
|
"* QUOTA \"INBOX\" (STORAGE 1024 1048576 MESSAGE 2 100)\r\n"
|
|
),
|
|
),
|
|
] {
|
|
assert_eq!(String::from_utf8(response.serialize()).unwrap(), expected);
|
|
}
|
|
}
|
|
}
|